// baltzo_localtimeoffsetutil.t.cpp                                   -*-C++-*-
#include <baltzo_localtimeoffsetutil.h>

#include <baltzo_localtimedescriptor.h>
#include <baltzo_defaultzoneinfocache.h>  // for testing only
#include <baltzo_testloader.h>            // for testing only
#include <baltzo_zoneinfo.h>
#include <baltzo_zoneinfocache.h>         // for testing only
#include <baltzo_zoneinfoutil.h>          // for testing only

#include <bsla_maybeunused.h>

#include <bslmt_barrier.h>       // case -1
#include <bslmt_configuration.h> // case -1
#include <bslmt_threadutil.h>    // case -1
#include <bdlt_epochutil.h>
#include <bdlt_iso8601util.h>                // case 5
#include <bslma_default.h>
#include <bslma_defaultallocatorguard.h>  // case 5
#include <bslma_testallocator.h>          // case 5

#include <bslmf_assert.h>

#include <bsls_assert.h>
#include <bsls_asserttest.h>
#include <bsls_review.h>
#include <bsls_stopwatch.h>
#include <bsls_types.h>

#include <bsl_cstdio.h>
#include <bsl_cstdlib.h>
#include <bsl_cstring.h>         // `strcmp`
#include <bsl_iostream.h>
#include <bsl_vector.h>          // case -1

#if defined(BSLS_PLATFORM_CMP_MSVC)
#define snprintf _snprintf
#endif

using namespace BloombergLP;
using namespace bsl;

// ============================================================================
//                              TEST PLAN
// ----------------------------------------------------------------------------
//                              Overview
//                              --------
// The component under test is a utility; however, as the functions provided
// all serve to set or report on local time offset information (consisting of
// value semantic types), the test strategy of this component more closely
// resembles that of a VST than of a typical utility.  In particular, we will
// informally categorize certain methods as "Primary Manipulators" and "Basic
// Accessors" validate them, and then use them in tests for other methods.
//
// Primary Manipulators:
//  - `configure` (the overload with two parameters)
//
// Basic Accessors:
//  - `loadTimezone`
//  - `loadLocalTimePeriod`
//
// ----------------------------------------------------------------------------
// CLASS METHODS
//                         *** local time offset methods ***
// [ 6] int localTimeOffset(int *result, const bdlt::Datetime& utc);
// [ 4] bdlt::CurrentTime::LLTOC setLoadLocalTimeOffsetCallback();
//
//                         *** configure methods ***
// [ 3] int configure();
// [ 3] int configure(const char *timezone);
// [ 2] int configure(const char *timezone, const bdlt::Datetime& utc);
//
//                         *** accessor methods ***
// [ 2] void loadLocalTimePeriod(LocalTimePeriod *localTimePeriod);
// [ 2] void loadTimezone(bsl::string      *timezone);
// [ 2] void loadTimezone(std::string      *timezone);
// [ 2] void loadTimezone(std::pmr::string *timezone);
// [ 6] int updateCount();
// [ 6] void loadLocalTimeOffset(int *result, const bdlt::Datetime& utc);
// [ 6] blsl::TimeInterval loadLocalTimeOffset(const bdlt::Datetime& utc);
//
// ----------------------------------------------------------------------------
// [ 1] BREATHING TEST
// [ 7] USAGE EXAMPLE
// [ 2] BOOTSTRAP1: int updateCount();
// [ 3] BOOTSTRAP2: int updateCount();
// [ 5] CONCERN: This component uses the default global allocator.
// [ 5] CONCERN: The static members have the expected initial values.
// [-1] CONCERN: The public methods of this component are *thread-safe*.
// [-2] CONCERN: Performance on cache hits.
// [-3] CONCERN: Performance on cache misses.

// ============================================================================
//                      STANDARD BDE ASSERT TEST MACRO
// ----------------------------------------------------------------------------

static int testStatus = 0;
static void aSsErT(int c, const char *s, int i)
{
    if (c) {
        cout << "Error " << __FILE__ << "(" << i << "): " << s
             << "    (failed)" << endl;
        if (testStatus >= 0 && testStatus <= 100) ++testStatus;
    }
}
#define ASSERT(X) { aSsErT(!(X), #X, __LINE__); }

// ============================================================================
//                   STANDARD BDE LOOP-ASSERT TEST MACROS
// ----------------------------------------------------------------------------

#define LOOP_ASSERT(I,X) { \
   if (!(X)) { cout << #I << ": " << I << "\n"; aSsErT(1, #X, __LINE__); }}

#define LOOP2_ASSERT(I,J,X) { \
   if (!(X)) { cout << #I << ": " << I << "\t" << #J << ": " \
              << J << "\n"; aSsErT(1, #X, __LINE__); } }

#define LOOP3_ASSERT(I,J,K,X) { \
   if (!(X)) { cout << #I << ": " << I << "\t" << #J << ": " \
                    << J << "\t" \
                    << #K << ": " << K <<  "\n"; aSsErT(1, #X, __LINE__); } }

// ============================================================================
//                     SEMI-STANDARD TEST OUTPUT MACROS
// ----------------------------------------------------------------------------

#define P(X) cout << #X " = " << (X) << endl; // Print identifier and value.
#define Q(X) cout << "<| " #X " |>" << endl;  // Quote identifier literally.
#define P_(X) cout << #X " = " << (X) << ", "<< flush; // P(X) without '\n'
#define T_  cout << "\t" << flush;          // Print a tab (w/o newline)
#define L_ __LINE__                           // current Line number

bool             g_verbose;
bool         g_veryVerbose;
bool     g_veryVeryVerbose;
bool g_veryVeryVeryVerbose;

// ============================================================================
//                     NEGATIVE-TEST MACRO ABBREVIATIONS
// ----------------------------------------------------------------------------

#define ASSERT_SAFE_PASS(EXPR) BSLS_ASSERTTEST_ASSERT_SAFE_PASS(EXPR)
#define ASSERT_SAFE_FAIL(EXPR) BSLS_ASSERTTEST_ASSERT_SAFE_FAIL(EXPR)
#define ASSERT_PASS(EXPR)      BSLS_ASSERTTEST_ASSERT_PASS(EXPR)
#define ASSERT_FAIL(EXPR)      BSLS_ASSERTTEST_ASSERT_FAIL(EXPR)
#define ASSERT_OPT_PASS(EXPR)  BSLS_ASSERTTEST_ASSERT_OPT_PASS(EXPR)
#define ASSERT_OPT_FAIL(EXPR)  BSLS_ASSERTTEST_ASSERT_OPT_FAIL(EXPR)

// ============================================================================
//                   GLOBAL TYPEDEFS/CONSTANTS FOR TESTING
// ----------------------------------------------------------------------------

typedef baltzo::LocalTimeOffsetUtil Util;

const char *NY  = "America/New_York";
const char *BE  = "Europe/Berlin";
const char *RY  = "Asia/Riyadh";
const char *SA  = "Asia/Saigon";
const char *GMT = "Etc/GMT";
const char *GP1 = "Etc/GMT+1";
const char *GM1 = "Etc/GMT-1";

// ============================================================================
//                             GLOBAL TEST DATA
// ----------------------------------------------------------------------------

const char *DEFAULT_TZ_ARRAY[]   = { NY, BE, RY, SA, GMT, GP1, GM1 };
const int   DEFAULT_NUM_TZ_ARRAY = sizeof  DEFAULT_TZ_ARRAY
                                 / sizeof *DEFAULT_TZ_ARRAY;

const bdlt::Datetime DEFAULT_DT_ARRAY[] = { bdlt::Datetime(2012,  1,  1),
                                           bdlt::Datetime(2013,  6, 20),
                                           bdlt::Datetime(2014, 12, 31)
                                          };
const int DEFAULT_NUM_DT_ARRAY = sizeof  DEFAULT_DT_ARRAY
                               / sizeof *DEFAULT_DT_ARRAY;

#ifdef BSLS_PLATFORM_CPU_32_BIT
#define SUFFICIENTLY_LONG_STRING "123456789012345678901234567890123"
#else  // 64_BIT
#define SUFFICIENTLY_LONG_STRING "12345678901234567890123456789012" \
                                 "123456789012345678901234567890123"
#endif
BSLMF_ASSERT(sizeof SUFFICIENTLY_LONG_STRING > sizeof(bsl::string));

BSLA_MAYBE_UNUSED const char *const LONG_STRING =
    "a_" SUFFICIENTLY_LONG_STRING;
BSLA_MAYBE_UNUSED const char *const LONGER_STRING =
    "ab_" SUFFICIENTLY_LONG_STRING;
BSLA_MAYBE_UNUSED const char *const LONGEST_STRING =
    "abc_" SUFFICIENTLY_LONG_STRING;

// ============================================================================
//                            TEST TIME ZONE DATA
// ----------------------------------------------------------------------------

// America/New_York
static const unsigned char AMERICA_NEW_YORK_DATA[] = {
    0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
    0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xeb,
    0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x9e, 0xa6, 0x1e, 0x70,
    0x9f, 0xba, 0xeb, 0x60, 0xa0, 0x86, 0x00, 0x70, 0xa1, 0x9a, 0xcd, 0x60,
    0xa2, 0x65, 0xe2, 0x70, 0xa3, 0x83, 0xe9, 0xe0, 0xa4, 0x6a, 0xae, 0x70,
    0xa5, 0x35, 0xa7, 0x60, 0xa6, 0x53, 0xca, 0xf0, 0xa7, 0x15, 0x89, 0x60,
    0xa8, 0x33, 0xac, 0xf0, 0xa8, 0xfe, 0xa5, 0xe0, 0xaa, 0x13, 0x8e, 0xf0,
    0xaa, 0xde, 0x87, 0xe0, 0xab, 0xf3, 0x70, 0xf0, 0xac, 0xbe, 0x69, 0xe0,
    0xad, 0xd3, 0x52, 0xf0, 0xae, 0x9e, 0x4b, 0xe0, 0xaf, 0xb3, 0x34, 0xf0,
    0xb0, 0x7e, 0x2d, 0xe0, 0xb1, 0x9c, 0x51, 0x70, 0xb2, 0x67, 0x4a, 0x60,
    0xb3, 0x7c, 0x33, 0x70, 0xb4, 0x47, 0x2c, 0x60, 0xb5, 0x5c, 0x15, 0x70,
    0xb6, 0x27, 0x0e, 0x60, 0xb7, 0x3b, 0xf7, 0x70, 0xb8, 0x06, 0xf0, 0x60,
    0xb9, 0x1b, 0xd9, 0x70, 0xb9, 0xe6, 0xd2, 0x60, 0xbb, 0x04, 0xf5, 0xf0,
    0xbb, 0xc6, 0xb4, 0x60, 0xbc, 0xe4, 0xd7, 0xf0, 0xbd, 0xaf, 0xd0, 0xe0,
    0xbe, 0xc4, 0xb9, 0xf0, 0xbf, 0x8f, 0xb2, 0xe0, 0xc0, 0xa4, 0x9b, 0xf0,
    0xc1, 0x6f, 0x94, 0xe0, 0xc2, 0x84, 0x7d, 0xf0, 0xc3, 0x4f, 0x76, 0xe0,
    0xc4, 0x64, 0x5f, 0xf0, 0xc5, 0x2f, 0x58, 0xe0, 0xc6, 0x4d, 0x7c, 0x70,
    0xc7, 0x0f, 0x3a, 0xe0, 0xc8, 0x2d, 0x5e, 0x70, 0xc8, 0xf8, 0x57, 0x60,
    0xca, 0x0d, 0x40, 0x70, 0xca, 0xd8, 0x39, 0x60, 0xcb, 0x88, 0xf0, 0x70,
    0xd2, 0x23, 0xf4, 0x70, 0xd2, 0x60, 0xfb, 0xe0, 0xd3, 0x75, 0xe4, 0xf0,
    0xd4, 0x40, 0xdd, 0xe0, 0xd5, 0x55, 0xc6, 0xf0, 0xd6, 0x20, 0xbf, 0xe0,
    0xd7, 0x35, 0xa8, 0xf0, 0xd8, 0x00, 0xa1, 0xe0, 0xd9, 0x15, 0x8a, 0xf0,
    0xd9, 0xe0, 0x83, 0xe0, 0xda, 0xfe, 0xa7, 0x70, 0xdb, 0xc0, 0x65, 0xe0,
    0xdc, 0xde, 0x89, 0x70, 0xdd, 0xa9, 0x82, 0x60, 0xde, 0xbe, 0x6b, 0x70,
    0xdf, 0x89, 0x64, 0x60, 0xe0, 0x9e, 0x4d, 0x70, 0xe1, 0x69, 0x46, 0x60,
    0xe2, 0x7e, 0x2f, 0x70, 0xe3, 0x49, 0x28, 0x60, 0xe4, 0x5e, 0x11, 0x70,
    0xe5, 0x57, 0x2e, 0xe0, 0xe6, 0x47, 0x2d, 0xf0, 0xe7, 0x37, 0x10, 0xe0,
    0xe8, 0x27, 0x0f, 0xf0, 0xe9, 0x16, 0xf2, 0xe0, 0xea, 0x06, 0xf1, 0xf0,
    0xea, 0xf6, 0xd4, 0xe0, 0xeb, 0xe6, 0xd3, 0xf0, 0xec, 0xd6, 0xb6, 0xe0,
    0xed, 0xc6, 0xb5, 0xf0, 0xee, 0xbf, 0xd3, 0x60, 0xef, 0xaf, 0xd2, 0x70,
    0xf0, 0x9f, 0xb5, 0x60, 0xf1, 0x8f, 0xb4, 0x70, 0xf2, 0x7f, 0x97, 0x60,
    0xf3, 0x6f, 0x96, 0x70, 0xf4, 0x5f, 0x79, 0x60, 0xf5, 0x4f, 0x78, 0x70,
    0xf6, 0x3f, 0x5b, 0x60, 0xf7, 0x2f, 0x5a, 0x70, 0xf8, 0x28, 0x77, 0xe0,
    0xf9, 0x0f, 0x3c, 0x70, 0xfa, 0x08, 0x59, 0xe0, 0xfa, 0xf8, 0x58, 0xf0,
    0xfb, 0xe8, 0x3b, 0xe0, 0xfc, 0xd8, 0x3a, 0xf0, 0xfd, 0xc8, 0x1d, 0xe0,
    0xfe, 0xb8, 0x1c, 0xf0, 0xff, 0xa7, 0xff, 0xe0, 0x00, 0x97, 0xfe, 0xf0,
    0x01, 0x87, 0xe1, 0xe0, 0x02, 0x77, 0xe0, 0xf0, 0x03, 0x70, 0xfe, 0x60,
    0x04, 0x60, 0xfd, 0x70, 0x05, 0x50, 0xe0, 0x60, 0x06, 0x40, 0xdf, 0x70,
    0x07, 0x30, 0xc2, 0x60, 0x07, 0x8d, 0x19, 0x70, 0x09, 0x10, 0xa4, 0x60,
    0x09, 0xad, 0x94, 0xf0, 0x0a, 0xf0, 0x86, 0x60, 0x0b, 0xe0, 0x85, 0x70,
    0x0c, 0xd9, 0xa2, 0xe0, 0x0d, 0xc0, 0x67, 0x70, 0x0e, 0xb9, 0x84, 0xe0,
    0x0f, 0xa9, 0x83, 0xf0, 0x10, 0x99, 0x66, 0xe0, 0x11, 0x89, 0x65, 0xf0,
    0x12, 0x79, 0x48, 0xe0, 0x13, 0x69, 0x47, 0xf0, 0x14, 0x59, 0x2a, 0xe0,
    0x15, 0x49, 0x29, 0xf0, 0x16, 0x39, 0x0c, 0xe0, 0x17, 0x29, 0x0b, 0xf0,
    0x18, 0x22, 0x29, 0x60, 0x19, 0x08, 0xed, 0xf0, 0x1a, 0x02, 0x0b, 0x60,
    0x1a, 0xf2, 0x0a, 0x70, 0x1b, 0xe1, 0xed, 0x60, 0x1c, 0xd1, 0xec, 0x70,
    0x1d, 0xc1, 0xcf, 0x60, 0x1e, 0xb1, 0xce, 0x70, 0x1f, 0xa1, 0xb1, 0x60,
    0x20, 0x76, 0x00, 0xf0, 0x21, 0x81, 0x93, 0x60, 0x22, 0x55, 0xe2, 0xf0,
    0x23, 0x6a, 0xaf, 0xe0, 0x24, 0x35, 0xc4, 0xf0, 0x25, 0x4a, 0x91, 0xe0,
    0x26, 0x15, 0xa6, 0xf0, 0x27, 0x2a, 0x73, 0xe0, 0x27, 0xfe, 0xc3, 0x70,
    0x29, 0x0a, 0x55, 0xe0, 0x29, 0xde, 0xa5, 0x70, 0x2a, 0xea, 0x37, 0xe0,
    0x2b, 0xbe, 0x87, 0x70, 0x2c, 0xd3, 0x54, 0x60, 0x2d, 0x9e, 0x69, 0x70,
    0x2e, 0xb3, 0x36, 0x60, 0x2f, 0x7e, 0x4b, 0x70, 0x30, 0x93, 0x18, 0x60,
    0x31, 0x67, 0x67, 0xf0, 0x32, 0x72, 0xfa, 0x60, 0x33, 0x47, 0x49, 0xf0,
    0x34, 0x52, 0xdc, 0x60, 0x35, 0x27, 0x2b, 0xf0, 0x36, 0x32, 0xbe, 0x60,
    0x37, 0x07, 0x0d, 0xf0, 0x38, 0x1b, 0xda, 0xe0, 0x38, 0xe6, 0xef, 0xf0,
    0x39, 0xfb, 0xbc, 0xe0, 0x3a, 0xc6, 0xd1, 0xf0, 0x3b, 0xdb, 0x9e, 0xe0,
    0x3c, 0xaf, 0xee, 0x70, 0x3d, 0xbb, 0x80, 0xe0, 0x3e, 0x8f, 0xd0, 0x70,
    0x3f, 0x9b, 0x62, 0xe0, 0x40, 0x6f, 0xb2, 0x70, 0x41, 0x84, 0x7f, 0x60,
    0x42, 0x4f, 0x94, 0x70, 0x43, 0x64, 0x61, 0x60, 0x44, 0x2f, 0x76, 0x70,
    0x45, 0x44, 0x43, 0x60, 0x45, 0xf3, 0xa8, 0xf0, 0x47, 0x2d, 0x5f, 0xe0,
    0x47, 0xd3, 0x8a, 0xf0, 0x49, 0x0d, 0x41, 0xe0, 0x49, 0xb3, 0x6c, 0xf0,
    0x4a, 0xed, 0x23, 0xe0, 0x4b, 0x9c, 0x89, 0x70, 0x4c, 0xd6, 0x40, 0x60,
    0x4d, 0x7c, 0x6b, 0x70, 0x4e, 0xb6, 0x22, 0x60, 0x4f, 0x5c, 0x4d, 0x70,
    0x50, 0x96, 0x04, 0x60, 0x51, 0x3c, 0x2f, 0x70, 0x52, 0x75, 0xe6, 0x60,
    0x53, 0x1c, 0x11, 0x70, 0x54, 0x55, 0xc8, 0x60, 0x54, 0xfb, 0xf3, 0x70,
    0x56, 0x35, 0xaa, 0x60, 0x56, 0xe5, 0x0f, 0xf0, 0x58, 0x1e, 0xc6, 0xe0,
    0x58, 0xc4, 0xf1, 0xf0, 0x59, 0xfe, 0xa8, 0xe0, 0x5a, 0xa4, 0xd3, 0xf0,
    0x5b, 0xde, 0x8a, 0xe0, 0x5c, 0x84, 0xb5, 0xf0, 0x5d, 0xbe, 0x6c, 0xe0,
    0x5e, 0x64, 0x97, 0xf0, 0x5f, 0x9e, 0x4e, 0xe0, 0x60, 0x4d, 0xb4, 0x70,
    0x61, 0x87, 0x6b, 0x60, 0x62, 0x2d, 0x96, 0x70, 0x63, 0x67, 0x4d, 0x60,
    0x64, 0x0d, 0x78, 0x70, 0x65, 0x47, 0x2f, 0x60, 0x65, 0xed, 0x5a, 0x70,
    0x67, 0x27, 0x11, 0x60, 0x67, 0xcd, 0x3c, 0x70, 0x69, 0x06, 0xf3, 0x60,
    0x69, 0xad, 0x1e, 0x70, 0x6a, 0xe6, 0xd5, 0x60, 0x6b, 0x96, 0x3a, 0xf0,
    0x6c, 0xcf, 0xf1, 0xe0, 0x6d, 0x76, 0x1c, 0xf0, 0x6e, 0xaf, 0xd3, 0xe0,
    0x6f, 0x55, 0xfe, 0xf0, 0x70, 0x8f, 0xb5, 0xe0, 0x71, 0x35, 0xe0, 0xf0,
    0x72, 0x6f, 0x97, 0xe0, 0x73, 0x15, 0xc2, 0xf0, 0x74, 0x4f, 0x79, 0xe0,
    0x74, 0xfe, 0xdf, 0x70, 0x76, 0x38, 0x96, 0x60, 0x76, 0xde, 0xc1, 0x70,
    0x78, 0x18, 0x78, 0x60, 0x78, 0xbe, 0xa3, 0x70, 0x79, 0xf8, 0x5a, 0x60,
    0x7a, 0x9e, 0x85, 0x70, 0x7b, 0xd8, 0x3c, 0x60, 0x7c, 0x7e, 0x67, 0x70,
    0x7d, 0xb8, 0x1e, 0x60, 0x7e, 0x5e, 0x49, 0x70, 0x7f, 0x98, 0x00, 0x60,
    0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
    0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
    0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
    0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
    0x02, 0x03, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
    0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
    0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
    0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
    0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
    0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
    0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
    0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
    0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
    0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
    0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
    0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
    0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
    0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
    0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
    0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0xff, 0xff, 0xc7, 0xc0, 0x01,
    0x00, 0xff, 0xff, 0xb9, 0xb0, 0x00, 0x04, 0xff, 0xff, 0xc7, 0xc0, 0x01,
    0x08, 0xff, 0xff, 0xc7, 0xc0, 0x01, 0x0c, 0x45, 0x44, 0x54, 0x00, 0x45,
    0x53, 0x54, 0x00, 0x45, 0x57, 0x54, 0x00, 0x45, 0x50, 0x54, 0x00, 0x00,
    0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x54, 0x5a, 0x69, 0x66, 0x32,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0x05, 0x00,
    0x00, 0x00, 0x14, 0xff, 0xff, 0xff, 0xff, 0x5e, 0x03, 0xf0, 0x90, 0xff,
    0xff, 0xff, 0xff, 0x9e, 0xa6, 0x1e, 0x70, 0xff, 0xff, 0xff, 0xff, 0x9f,
    0xba, 0xeb, 0x60, 0xff, 0xff, 0xff, 0xff, 0xa0, 0x86, 0x00, 0x70, 0xff,
    0xff, 0xff, 0xff, 0xa1, 0x9a, 0xcd, 0x60, 0xff, 0xff, 0xff, 0xff, 0xa2,
    0x65, 0xe2, 0x70, 0xff, 0xff, 0xff, 0xff, 0xa3, 0x83, 0xe9, 0xe0, 0xff,
    0xff, 0xff, 0xff, 0xa4, 0x6a, 0xae, 0x70, 0xff, 0xff, 0xff, 0xff, 0xa5,
    0x35, 0xa7, 0x60, 0xff, 0xff, 0xff, 0xff, 0xa6, 0x53, 0xca, 0xf0, 0xff,
    0xff, 0xff, 0xff, 0xa7, 0x15, 0x89, 0x60, 0xff, 0xff, 0xff, 0xff, 0xa8,
    0x33, 0xac, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xa8, 0xfe, 0xa5, 0xe0, 0xff,
    0xff, 0xff, 0xff, 0xaa, 0x13, 0x8e, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xaa,
    0xde, 0x87, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xab, 0xf3, 0x70, 0xf0, 0xff,
    0xff, 0xff, 0xff, 0xac, 0xbe, 0x69, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xad,
    0xd3, 0x52, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xae, 0x9e, 0x4b, 0xe0, 0xff,
    0xff, 0xff, 0xff, 0xaf, 0xb3, 0x34, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xb0,
    0x7e, 0x2d, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xb1, 0x9c, 0x51, 0x70, 0xff,
    0xff, 0xff, 0xff, 0xb2, 0x67, 0x4a, 0x60, 0xff, 0xff, 0xff, 0xff, 0xb3,
    0x7c, 0x33, 0x70, 0xff, 0xff, 0xff, 0xff, 0xb4, 0x47, 0x2c, 0x60, 0xff,
    0xff, 0xff, 0xff, 0xb5, 0x5c, 0x15, 0x70, 0xff, 0xff, 0xff, 0xff, 0xb6,
    0x27, 0x0e, 0x60, 0xff, 0xff, 0xff, 0xff, 0xb7, 0x3b, 0xf7, 0x70, 0xff,
    0xff, 0xff, 0xff, 0xb8, 0x06, 0xf0, 0x60, 0xff, 0xff, 0xff, 0xff, 0xb9,
    0x1b, 0xd9, 0x70, 0xff, 0xff, 0xff, 0xff, 0xb9, 0xe6, 0xd2, 0x60, 0xff,
    0xff, 0xff, 0xff, 0xbb, 0x04, 0xf5, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xbb,
    0xc6, 0xb4, 0x60, 0xff, 0xff, 0xff, 0xff, 0xbc, 0xe4, 0xd7, 0xf0, 0xff,
    0xff, 0xff, 0xff, 0xbd, 0xaf, 0xd0, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xbe,
    0xc4, 0xb9, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x8f, 0xb2, 0xe0, 0xff,
    0xff, 0xff, 0xff, 0xc0, 0xa4, 0x9b, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xc1,
    0x6f, 0x94, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xc2, 0x84, 0x7d, 0xf0, 0xff,
    0xff, 0xff, 0xff, 0xc3, 0x4f, 0x76, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xc4,
    0x64, 0x5f, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xc5, 0x2f, 0x58, 0xe0, 0xff,
    0xff, 0xff, 0xff, 0xc6, 0x4d, 0x7c, 0x70, 0xff, 0xff, 0xff, 0xff, 0xc7,
    0x0f, 0x3a, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xc8, 0x2d, 0x5e, 0x70, 0xff,
    0xff, 0xff, 0xff, 0xc8, 0xf8, 0x57, 0x60, 0xff, 0xff, 0xff, 0xff, 0xca,
    0x0d, 0x40, 0x70, 0xff, 0xff, 0xff, 0xff, 0xca, 0xd8, 0x39, 0x60, 0xff,
    0xff, 0xff, 0xff, 0xcb, 0x88, 0xf0, 0x70, 0xff, 0xff, 0xff, 0xff, 0xd2,
    0x23, 0xf4, 0x70, 0xff, 0xff, 0xff, 0xff, 0xd2, 0x60, 0xfb, 0xe0, 0xff,
    0xff, 0xff, 0xff, 0xd3, 0x75, 0xe4, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xd4,
    0x40, 0xdd, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xd5, 0x55, 0xc6, 0xf0, 0xff,
    0xff, 0xff, 0xff, 0xd6, 0x20, 0xbf, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xd7,
    0x35, 0xa8, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xd8, 0x00, 0xa1, 0xe0, 0xff,
    0xff, 0xff, 0xff, 0xd9, 0x15, 0x8a, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xd9,
    0xe0, 0x83, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xda, 0xfe, 0xa7, 0x70, 0xff,
    0xff, 0xff, 0xff, 0xdb, 0xc0, 0x65, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xdc,
    0xde, 0x89, 0x70, 0xff, 0xff, 0xff, 0xff, 0xdd, 0xa9, 0x82, 0x60, 0xff,
    0xff, 0xff, 0xff, 0xde, 0xbe, 0x6b, 0x70, 0xff, 0xff, 0xff, 0xff, 0xdf,
    0x89, 0x64, 0x60, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x9e, 0x4d, 0x70, 0xff,
    0xff, 0xff, 0xff, 0xe1, 0x69, 0x46, 0x60, 0xff, 0xff, 0xff, 0xff, 0xe2,
    0x7e, 0x2f, 0x70, 0xff, 0xff, 0xff, 0xff, 0xe3, 0x49, 0x28, 0x60, 0xff,
    0xff, 0xff, 0xff, 0xe4, 0x5e, 0x11, 0x70, 0xff, 0xff, 0xff, 0xff, 0xe5,
    0x57, 0x2e, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xe6, 0x47, 0x2d, 0xf0, 0xff,
    0xff, 0xff, 0xff, 0xe7, 0x37, 0x10, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xe8,
    0x27, 0x0f, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xe9, 0x16, 0xf2, 0xe0, 0xff,
    0xff, 0xff, 0xff, 0xea, 0x06, 0xf1, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xea,
    0xf6, 0xd4, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xeb, 0xe6, 0xd3, 0xf0, 0xff,
    0xff, 0xff, 0xff, 0xec, 0xd6, 0xb6, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xed,
    0xc6, 0xb5, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xee, 0xbf, 0xd3, 0x60, 0xff,
    0xff, 0xff, 0xff, 0xef, 0xaf, 0xd2, 0x70, 0xff, 0xff, 0xff, 0xff, 0xf0,
    0x9f, 0xb5, 0x60, 0xff, 0xff, 0xff, 0xff, 0xf1, 0x8f, 0xb4, 0x70, 0xff,
    0xff, 0xff, 0xff, 0xf2, 0x7f, 0x97, 0x60, 0xff, 0xff, 0xff, 0xff, 0xf3,
    0x6f, 0x96, 0x70, 0xff, 0xff, 0xff, 0xff, 0xf4, 0x5f, 0x79, 0x60, 0xff,
    0xff, 0xff, 0xff, 0xf5, 0x4f, 0x78, 0x70, 0xff, 0xff, 0xff, 0xff, 0xf6,
    0x3f, 0x5b, 0x60, 0xff, 0xff, 0xff, 0xff, 0xf7, 0x2f, 0x5a, 0x70, 0xff,
    0xff, 0xff, 0xff, 0xf8, 0x28, 0x77, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xf9,
    0x0f, 0x3c, 0x70, 0xff, 0xff, 0xff, 0xff, 0xfa, 0x08, 0x59, 0xe0, 0xff,
    0xff, 0xff, 0xff, 0xfa, 0xf8, 0x58, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xfb,
    0xe8, 0x3b, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xd8, 0x3a, 0xf0, 0xff,
    0xff, 0xff, 0xff, 0xfd, 0xc8, 0x1d, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xfe,
    0xb8, 0x1c, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa7, 0xff, 0xe0, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x97, 0xfe, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x01,
    0x87, 0xe1, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x02, 0x77, 0xe0, 0xf0, 0x00,
    0x00, 0x00, 0x00, 0x03, 0x70, 0xfe, 0x60, 0x00, 0x00, 0x00, 0x00, 0x04,
    0x60, 0xfd, 0x70, 0x00, 0x00, 0x00, 0x00, 0x05, 0x50, 0xe0, 0x60, 0x00,
    0x00, 0x00, 0x00, 0x06, 0x40, 0xdf, 0x70, 0x00, 0x00, 0x00, 0x00, 0x07,
    0x30, 0xc2, 0x60, 0x00, 0x00, 0x00, 0x00, 0x07, 0x8d, 0x19, 0x70, 0x00,
    0x00, 0x00, 0x00, 0x09, 0x10, 0xa4, 0x60, 0x00, 0x00, 0x00, 0x00, 0x09,
    0xad, 0x94, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xf0, 0x86, 0x60, 0x00,
    0x00, 0x00, 0x00, 0x0b, 0xe0, 0x85, 0x70, 0x00, 0x00, 0x00, 0x00, 0x0c,
    0xd9, 0xa2, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x0d, 0xc0, 0x67, 0x70, 0x00,
    0x00, 0x00, 0x00, 0x0e, 0xb9, 0x84, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x0f,
    0xa9, 0x83, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x10, 0x99, 0x66, 0xe0, 0x00,
    0x00, 0x00, 0x00, 0x11, 0x89, 0x65, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x12,
    0x79, 0x48, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x13, 0x69, 0x47, 0xf0, 0x00,
    0x00, 0x00, 0x00, 0x14, 0x59, 0x2a, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x15,
    0x49, 0x29, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x16, 0x39, 0x0c, 0xe0, 0x00,
    0x00, 0x00, 0x00, 0x17, 0x29, 0x0b, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x18,
    0x22, 0x29, 0x60, 0x00, 0x00, 0x00, 0x00, 0x19, 0x08, 0xed, 0xf0, 0x00,
    0x00, 0x00, 0x00, 0x1a, 0x02, 0x0b, 0x60, 0x00, 0x00, 0x00, 0x00, 0x1a,
    0xf2, 0x0a, 0x70, 0x00, 0x00, 0x00, 0x00, 0x1b, 0xe1, 0xed, 0x60, 0x00,
    0x00, 0x00, 0x00, 0x1c, 0xd1, 0xec, 0x70, 0x00, 0x00, 0x00, 0x00, 0x1d,
    0xc1, 0xcf, 0x60, 0x00, 0x00, 0x00, 0x00, 0x1e, 0xb1, 0xce, 0x70, 0x00,
    0x00, 0x00, 0x00, 0x1f, 0xa1, 0xb1, 0x60, 0x00, 0x00, 0x00, 0x00, 0x20,
    0x76, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x21, 0x81, 0x93, 0x60, 0x00,
    0x00, 0x00, 0x00, 0x22, 0x55, 0xe2, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x23,
    0x6a, 0xaf, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x24, 0x35, 0xc4, 0xf0, 0x00,
    0x00, 0x00, 0x00, 0x25, 0x4a, 0x91, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x26,
    0x15, 0xa6, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x27, 0x2a, 0x73, 0xe0, 0x00,
    0x00, 0x00, 0x00, 0x27, 0xfe, 0xc3, 0x70, 0x00, 0x00, 0x00, 0x00, 0x29,
    0x0a, 0x55, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x29, 0xde, 0xa5, 0x70, 0x00,
    0x00, 0x00, 0x00, 0x2a, 0xea, 0x37, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x2b,
    0xbe, 0x87, 0x70, 0x00, 0x00, 0x00, 0x00, 0x2c, 0xd3, 0x54, 0x60, 0x00,
    0x00, 0x00, 0x00, 0x2d, 0x9e, 0x69, 0x70, 0x00, 0x00, 0x00, 0x00, 0x2e,
    0xb3, 0x36, 0x60, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x7e, 0x4b, 0x70, 0x00,
    0x00, 0x00, 0x00, 0x30, 0x93, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x31,
    0x67, 0x67, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x32, 0x72, 0xfa, 0x60, 0x00,
    0x00, 0x00, 0x00, 0x33, 0x47, 0x49, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x34,
    0x52, 0xdc, 0x60, 0x00, 0x00, 0x00, 0x00, 0x35, 0x27, 0x2b, 0xf0, 0x00,
    0x00, 0x00, 0x00, 0x36, 0x32, 0xbe, 0x60, 0x00, 0x00, 0x00, 0x00, 0x37,
    0x07, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x38, 0x1b, 0xda, 0xe0, 0x00,
    0x00, 0x00, 0x00, 0x38, 0xe6, 0xef, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x39,
    0xfb, 0xbc, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x3a, 0xc6, 0xd1, 0xf0, 0x00,
    0x00, 0x00, 0x00, 0x3b, 0xdb, 0x9e, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x3c,
    0xaf, 0xee, 0x70, 0x00, 0x00, 0x00, 0x00, 0x3d, 0xbb, 0x80, 0xe0, 0x00,
    0x00, 0x00, 0x00, 0x3e, 0x8f, 0xd0, 0x70, 0x00, 0x00, 0x00, 0x00, 0x3f,
    0x9b, 0x62, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x40, 0x6f, 0xb2, 0x70, 0x00,
    0x00, 0x00, 0x00, 0x41, 0x84, 0x7f, 0x60, 0x00, 0x00, 0x00, 0x00, 0x42,
    0x4f, 0x94, 0x70, 0x00, 0x00, 0x00, 0x00, 0x43, 0x64, 0x61, 0x60, 0x00,
    0x00, 0x00, 0x00, 0x44, 0x2f, 0x76, 0x70, 0x00, 0x00, 0x00, 0x00, 0x45,
    0x44, 0x43, 0x60, 0x00, 0x00, 0x00, 0x00, 0x45, 0xf3, 0xa8, 0xf0, 0x00,
    0x00, 0x00, 0x00, 0x47, 0x2d, 0x5f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x47,
    0xd3, 0x8a, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x49, 0x0d, 0x41, 0xe0, 0x00,
    0x00, 0x00, 0x00, 0x49, 0xb3, 0x6c, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x4a,
    0xed, 0x23, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x9c, 0x89, 0x70, 0x00,
    0x00, 0x00, 0x00, 0x4c, 0xd6, 0x40, 0x60, 0x00, 0x00, 0x00, 0x00, 0x4d,
    0x7c, 0x6b, 0x70, 0x00, 0x00, 0x00, 0x00, 0x4e, 0xb6, 0x22, 0x60, 0x00,
    0x00, 0x00, 0x00, 0x4f, 0x5c, 0x4d, 0x70, 0x00, 0x00, 0x00, 0x00, 0x50,
    0x96, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x51, 0x3c, 0x2f, 0x70, 0x00,
    0x00, 0x00, 0x00, 0x52, 0x75, 0xe6, 0x60, 0x00, 0x00, 0x00, 0x00, 0x53,
    0x1c, 0x11, 0x70, 0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0xc8, 0x60, 0x00,
    0x00, 0x00, 0x00, 0x54, 0xfb, 0xf3, 0x70, 0x00, 0x00, 0x00, 0x00, 0x56,
    0x35, 0xaa, 0x60, 0x00, 0x00, 0x00, 0x00, 0x56, 0xe5, 0x0f, 0xf0, 0x00,
    0x00, 0x00, 0x00, 0x58, 0x1e, 0xc6, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x58,
    0xc4, 0xf1, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x59, 0xfe, 0xa8, 0xe0, 0x00,
    0x00, 0x00, 0x00, 0x5a, 0xa4, 0xd3, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x5b,
    0xde, 0x8a, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x84, 0xb5, 0xf0, 0x00,
    0x00, 0x00, 0x00, 0x5d, 0xbe, 0x6c, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x5e,
    0x64, 0x97, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x9e, 0x4e, 0xe0, 0x00,
    0x00, 0x00, 0x00, 0x60, 0x4d, 0xb4, 0x70, 0x00, 0x00, 0x00, 0x00, 0x61,
    0x87, 0x6b, 0x60, 0x00, 0x00, 0x00, 0x00, 0x62, 0x2d, 0x96, 0x70, 0x00,
    0x00, 0x00, 0x00, 0x63, 0x67, 0x4d, 0x60, 0x00, 0x00, 0x00, 0x00, 0x64,
    0x0d, 0x78, 0x70, 0x00, 0x00, 0x00, 0x00, 0x65, 0x47, 0x2f, 0x60, 0x00,
    0x00, 0x00, 0x00, 0x65, 0xed, 0x5a, 0x70, 0x00, 0x00, 0x00, 0x00, 0x67,
    0x27, 0x11, 0x60, 0x00, 0x00, 0x00, 0x00, 0x67, 0xcd, 0x3c, 0x70, 0x00,
    0x00, 0x00, 0x00, 0x69, 0x06, 0xf3, 0x60, 0x00, 0x00, 0x00, 0x00, 0x69,
    0xad, 0x1e, 0x70, 0x00, 0x00, 0x00, 0x00, 0x6a, 0xe6, 0xd5, 0x60, 0x00,
    0x00, 0x00, 0x00, 0x6b, 0x96, 0x3a, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x6c,
    0xcf, 0xf1, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x6d, 0x76, 0x1c, 0xf0, 0x00,
    0x00, 0x00, 0x00, 0x6e, 0xaf, 0xd3, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x6f,
    0x55, 0xfe, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0xb5, 0xe0, 0x00,
    0x00, 0x00, 0x00, 0x71, 0x35, 0xe0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x72,
    0x6f, 0x97, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x73, 0x15, 0xc2, 0xf0, 0x00,
    0x00, 0x00, 0x00, 0x74, 0x4f, 0x79, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x74,
    0xfe, 0xdf, 0x70, 0x00, 0x00, 0x00, 0x00, 0x76, 0x38, 0x96, 0x60, 0x00,
    0x00, 0x00, 0x00, 0x76, 0xde, 0xc1, 0x70, 0x00, 0x00, 0x00, 0x00, 0x78,
    0x18, 0x78, 0x60, 0x00, 0x00, 0x00, 0x00, 0x78, 0xbe, 0xa3, 0x70, 0x00,
    0x00, 0x00, 0x00, 0x79, 0xf8, 0x5a, 0x60, 0x00, 0x00, 0x00, 0x00, 0x7a,
    0x9e, 0x85, 0x70, 0x00, 0x00, 0x00, 0x00, 0x7b, 0xd8, 0x3c, 0x60, 0x00,
    0x00, 0x00, 0x00, 0x7c, 0x7e, 0x67, 0x70, 0x00, 0x00, 0x00, 0x00, 0x7d,
    0xb8, 0x1e, 0x60, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x5e, 0x49, 0x70, 0x00,
    0x00, 0x00, 0x00, 0x7f, 0x98, 0x00, 0x60, 0x02, 0x01, 0x02, 0x01, 0x02,
    0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,
    0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,
    0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,
    0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x03, 0x04, 0x02, 0x01,
    0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
    0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
    0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
    0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
    0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
    0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
    0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
    0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
    0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
    0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
    0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
    0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
    0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
    0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
    0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
    0x02, 0x01, 0x02, 0xff, 0xff, 0xba, 0x9e, 0x00, 0x00, 0xff, 0xff, 0xc7,
    0xc0, 0x01, 0x04, 0xff, 0xff, 0xb9, 0xb0, 0x00, 0x08, 0xff, 0xff, 0xc7,
    0xc0, 0x01, 0x0c, 0xff, 0xff, 0xc7, 0xc0, 0x01, 0x10, 0x4c, 0x4d, 0x54,
    0x00, 0x45, 0x44, 0x54, 0x00, 0x45, 0x53, 0x54, 0x00, 0x45, 0x57, 0x54,
    0x00, 0x45, 0x50, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
    0x00, 0x00, 0x01, 0x0a, 0x45, 0x53, 0x54, 0x35, 0x45, 0x44, 0x54, 0x2c,
    0x4d, 0x33, 0x2e, 0x32, 0x2e, 0x30, 0x2c, 0x4d, 0x31, 0x31, 0x2e, 0x31,
    0x2e, 0x30, 0x0a
};

// GMT
static const unsigned char GMT_DATA[] = {
    0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
    0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x47, 0x4d, 0x54, 0x00, 0x00, 0x00, 0x54, 0x5a, 0x69, 0x66,
    0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
    0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x4d,
    0x54, 0x00, 0x00, 0x00, 0x0a, 0x47, 0x4d, 0x54, 0x30, 0x0a,
};

// Europe/Rome
static const unsigned char EUROPE_ROME_DATA[] = {
    0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,
    0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa,
    0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x09, 0x9b, 0x37, 0xa6, 0xf0,
    0x9b, 0xd5, 0xda, 0xf0, 0x9c, 0xc5, 0xcb, 0xf0, 0x9d, 0xb5, 0xbc, 0xf0,
    0x9e, 0x89, 0xfe, 0x70, 0x9f, 0x9e, 0xd9, 0x70, 0xa0, 0x60, 0xa5, 0xf0,
    0xa1, 0x7e, 0xbb, 0x70, 0xa2, 0x5c, 0x37, 0x70, 0xa3, 0x4c, 0x28, 0x70,
    0xc8, 0x6c, 0x35, 0xf0, 0xcc, 0xe7, 0x4b, 0x10, 0xcd, 0xa9, 0x17, 0x90,
    0xce, 0xa2, 0x43, 0x10, 0xcf, 0x92, 0x34, 0x10, 0xd0, 0x07, 0x5f, 0x60,
    0xd0, 0x6e, 0x42, 0x70, 0xd1, 0x72, 0x16, 0x10, 0xd2, 0x4c, 0xd2, 0xf0,
    0xd3, 0x3e, 0x31, 0x90, 0xd4, 0x49, 0xd2, 0x10, 0xd5, 0x1d, 0xf7, 0x70,
    0xd6, 0x29, 0x97, 0xf0, 0xd6, 0xeb, 0x80, 0x90, 0xd8, 0x09, 0x96, 0x10,
    0xf9, 0x33, 0xb5, 0xf0, 0xf9, 0xd9, 0xc4, 0xe0, 0xfb, 0x1c, 0xd2, 0x70,
    0xfb, 0xb9, 0xa6, 0xe0, 0xfc, 0xfc, 0xb4, 0x70, 0xfd, 0x99, 0x88, 0xe0,
    0xfe, 0xe5, 0xd0, 0xf0, 0xff, 0x82, 0xa5, 0x60, 0x00, 0xc5, 0xb2, 0xf0,
    0x01, 0x62, 0x87, 0x60, 0x02, 0x9c, 0x5a, 0x70, 0x03, 0x42, 0x77, 0x70,
    0x04, 0x85, 0x76, 0xf0, 0x05, 0x2b, 0x85, 0xe0, 0x06, 0x6e, 0x93, 0x70,
    0x07, 0x0b, 0x67, 0xe0, 0x08, 0x45, 0x3a, 0xf0, 0x08, 0xeb, 0x49, 0xe0,
    0x0a, 0x2e, 0x57, 0x70, 0x0a, 0xcb, 0x39, 0xf0, 0x0c, 0x0e, 0x39, 0x70,
    0x0c, 0xab, 0x1b, 0xf0, 0x0d, 0xe4, 0xe0, 0xf0, 0x0e, 0x8a, 0xfd, 0xf0,
    0x0f, 0xcd, 0xfd, 0x70, 0x10, 0x74, 0x1a, 0x70, 0x11, 0xad, 0xdf, 0x70,
    0x12, 0x53, 0xfc, 0x70, 0x12, 0xce, 0x97, 0xf0, 0x13, 0x4d, 0x44, 0x10,
    0x14, 0x33, 0xfa, 0x90, 0x15, 0x23, 0xeb, 0x90, 0x16, 0x13, 0xdc, 0x90,
    0x17, 0x03, 0xcd, 0x90, 0x17, 0xf3, 0xbe, 0x90, 0x18, 0xe3, 0xaf, 0x90,
    0x19, 0xd3, 0xa0, 0x90, 0x1a, 0xc3, 0x91, 0x90, 0x1b, 0xbc, 0xbd, 0x10,
    0x1c, 0xac, 0xae, 0x10, 0x1d, 0x9c, 0x9f, 0x10, 0x1e, 0x8c, 0x90, 0x10,
    0x1f, 0x7c, 0x81, 0x10, 0x20, 0x6c, 0x72, 0x10, 0x21, 0x5c, 0x63, 0x10,
    0x22, 0x4c, 0x54, 0x10, 0x23, 0x3c, 0x45, 0x10, 0x24, 0x2c, 0x36, 0x10,
    0x25, 0x1c, 0x27, 0x10, 0x26, 0x0c, 0x18, 0x10, 0x27, 0x05, 0x43, 0x90,
    0x27, 0xf5, 0x34, 0x90, 0x28, 0xe5, 0x25, 0x90, 0x29, 0xd5, 0x16, 0x90,
    0x2a, 0xc5, 0x07, 0x90, 0x2b, 0xb4, 0xf8, 0x90, 0x2c, 0xa4, 0xe9, 0x90,
    0x2d, 0x94, 0xda, 0x90, 0x2e, 0x84, 0xcb, 0x90, 0x2f, 0x74, 0xbc, 0x90,
    0x30, 0x64, 0xad, 0x90, 0x31, 0x5d, 0xd9, 0x10, 0x32, 0x72, 0xb4, 0x10,
    0x33, 0x3d, 0xbb, 0x10, 0x34, 0x52, 0x96, 0x10, 0x35, 0x1d, 0x9d, 0x10,
    0x36, 0x32, 0x78, 0x10, 0x36, 0xfd, 0x7f, 0x10, 0x38, 0x1b, 0x94, 0x90,
    0x38, 0xdd, 0x61, 0x10, 0x39, 0xfb, 0x76, 0x90, 0x3a, 0xbd, 0x43, 0x10,
    0x3b, 0xdb, 0x58, 0x90, 0x3c, 0xa6, 0x5f, 0x90, 0x3d, 0xbb, 0x3a, 0x90,
    0x3e, 0x86, 0x41, 0x90, 0x3f, 0x9b, 0x1c, 0x90, 0x40, 0x66, 0x23, 0x90,
    0x41, 0x84, 0x39, 0x10, 0x42, 0x46, 0x05, 0x90, 0x43, 0x64, 0x1b, 0x10,
    0x44, 0x25, 0xe7, 0x90, 0x45, 0x43, 0xfd, 0x10, 0x46, 0x05, 0xc9, 0x90,
    0x47, 0x23, 0xdf, 0x10, 0x47, 0xee, 0xe6, 0x10, 0x49, 0x03, 0xc1, 0x10,
    0x49, 0xce, 0xc8, 0x10, 0x4a, 0xe3, 0xa3, 0x10, 0x4b, 0xae, 0xaa, 0x10,
    0x4c, 0xcc, 0xbf, 0x90, 0x4d, 0x8e, 0x8c, 0x10, 0x4e, 0xac, 0xa1, 0x90,
    0x4f, 0x6e, 0x6e, 0x10, 0x50, 0x8c, 0x83, 0x90, 0x51, 0x57, 0x8a, 0x90,
    0x52, 0x6c, 0x65, 0x90, 0x53, 0x37, 0x6c, 0x90, 0x54, 0x4c, 0x47, 0x90,
    0x55, 0x17, 0x4e, 0x90, 0x56, 0x2c, 0x29, 0x90, 0x56, 0xf7, 0x30, 0x90,
    0x58, 0x15, 0x46, 0x10, 0x58, 0xd7, 0x12, 0x90, 0x59, 0xf5, 0x28, 0x10,
    0x5a, 0xb6, 0xf4, 0x90, 0x5b, 0xd5, 0x0a, 0x10, 0x5c, 0xa0, 0x11, 0x10,
    0x5d, 0xb4, 0xec, 0x10, 0x5e, 0x7f, 0xf3, 0x10, 0x5f, 0x94, 0xce, 0x10,
    0x60, 0x5f, 0xd5, 0x10, 0x61, 0x7d, 0xea, 0x90, 0x62, 0x3f, 0xb7, 0x10,
    0x63, 0x5d, 0xcc, 0x90, 0x64, 0x1f, 0x99, 0x10, 0x65, 0x3d, 0xae, 0x90,
    0x66, 0x08, 0xb5, 0x90, 0x67, 0x1d, 0x90, 0x90, 0x67, 0xe8, 0x97, 0x90,
    0x68, 0xfd, 0x72, 0x90, 0x69, 0xc8, 0x79, 0x90, 0x6a, 0xdd, 0x54, 0x90,
    0x6b, 0xa8, 0x5b, 0x90, 0x6c, 0xc6, 0x71, 0x10, 0x6d, 0x88, 0x3d, 0x90,
    0x6e, 0xa6, 0x53, 0x10, 0x6f, 0x68, 0x1f, 0x90, 0x70, 0x86, 0x35, 0x10,
    0x71, 0x51, 0x3c, 0x10, 0x72, 0x66, 0x17, 0x10, 0x73, 0x31, 0x1e, 0x10,
    0x74, 0x45, 0xf9, 0x10, 0x75, 0x11, 0x00, 0x10, 0x76, 0x2f, 0x15, 0x90,
    0x76, 0xf0, 0xe2, 0x10, 0x78, 0x0e, 0xf7, 0x90, 0x78, 0xd0, 0xc4, 0x10,
    0x79, 0xee, 0xd9, 0x90, 0x7a, 0xb0, 0xa6, 0x10, 0x7b, 0xce, 0xbb, 0x90,
    0x7c, 0x99, 0xc2, 0x90, 0x7d, 0xae, 0x9d, 0x90, 0x7e, 0x79, 0xa4, 0x90,
    0x7f, 0x8e, 0x7f, 0x90, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
    0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x01, 0x02, 0x01, 0x00,
    0x01, 0x00, 0x01, 0x00, 0x01, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02,
    0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x00,
    0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x03, 0x04, 0x05,
    0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05,
    0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05,
    0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05,
    0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05,
    0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05,
    0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05,
    0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05,
    0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05,
    0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05,
    0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x00, 0x00, 0x1c, 0x20, 0x01, 0x00,
    0x00, 0x00, 0x0e, 0x10, 0x00, 0x05, 0x00, 0x00, 0x1c, 0x20, 0x01, 0x00,
    0x00, 0x00, 0x0e, 0x10, 0x00, 0x05, 0x00, 0x00, 0x1c, 0x20, 0x01, 0x00,
    0x00, 0x00, 0x0e, 0x10, 0x00, 0x05, 0x43, 0x45, 0x53, 0x54, 0x00, 0x43,
    0x45, 0x54, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00,
    0x00, 0x01, 0x01, 0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0xac, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x11, 0xff,
    0xff, 0xff, 0xff, 0x3d, 0xbe, 0x1e, 0xcc, 0xff, 0xff, 0xff, 0xff, 0x70,
    0xbc, 0x83, 0xcc, 0xff, 0xff, 0xff, 0xff, 0x9b, 0x37, 0xa6, 0xf0, 0xff,
    0xff, 0xff, 0xff, 0x9b, 0xd5, 0xda, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x9c,
    0xc5, 0xcb, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x9d, 0xb5, 0xbc, 0xf0, 0xff,
    0xff, 0xff, 0xff, 0x9e, 0x89, 0xfe, 0x70, 0xff, 0xff, 0xff, 0xff, 0x9f,
    0x9e, 0xd9, 0x70, 0xff, 0xff, 0xff, 0xff, 0xa0, 0x60, 0xa5, 0xf0, 0xff,
    0xff, 0xff, 0xff, 0xa1, 0x7e, 0xbb, 0x70, 0xff, 0xff, 0xff, 0xff, 0xa2,
    0x5c, 0x37, 0x70, 0xff, 0xff, 0xff, 0xff, 0xa3, 0x4c, 0x28, 0x70, 0xff,
    0xff, 0xff, 0xff, 0xc8, 0x6c, 0x35, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xcc,
    0xe7, 0x4b, 0x10, 0xff, 0xff, 0xff, 0xff, 0xcd, 0xa9, 0x17, 0x90, 0xff,
    0xff, 0xff, 0xff, 0xce, 0xa2, 0x43, 0x10, 0xff, 0xff, 0xff, 0xff, 0xcf,
    0x92, 0x34, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd0, 0x07, 0x5f, 0x60, 0xff,
    0xff, 0xff, 0xff, 0xd0, 0x6e, 0x42, 0x70, 0xff, 0xff, 0xff, 0xff, 0xd1,
    0x72, 0x16, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd2, 0x4c, 0xd2, 0xf0, 0xff,
    0xff, 0xff, 0xff, 0xd3, 0x3e, 0x31, 0x90, 0xff, 0xff, 0xff, 0xff, 0xd4,
    0x49, 0xd2, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd5, 0x1d, 0xf7, 0x70, 0xff,
    0xff, 0xff, 0xff, 0xd6, 0x29, 0x97, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xd6,
    0xeb, 0x80, 0x90, 0xff, 0xff, 0xff, 0xff, 0xd8, 0x09, 0x96, 0x10, 0xff,
    0xff, 0xff, 0xff, 0xf9, 0x33, 0xb5, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xf9,
    0xd9, 0xc4, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xfb, 0x1c, 0xd2, 0x70, 0xff,
    0xff, 0xff, 0xff, 0xfb, 0xb9, 0xa6, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xfc,
    0xfc, 0xb4, 0x70, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x99, 0x88, 0xe0, 0xff,
    0xff, 0xff, 0xff, 0xfe, 0xe5, 0xd0, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff,
    0x82, 0xa5, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc5, 0xb2, 0xf0, 0x00,
    0x00, 0x00, 0x00, 0x01, 0x62, 0x87, 0x60, 0x00, 0x00, 0x00, 0x00, 0x02,
    0x9c, 0x5a, 0x70, 0x00, 0x00, 0x00, 0x00, 0x03, 0x42, 0x77, 0x70, 0x00,
    0x00, 0x00, 0x00, 0x04, 0x85, 0x76, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x05,
    0x2b, 0x85, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x06, 0x6e, 0x93, 0x70, 0x00,
    0x00, 0x00, 0x00, 0x07, 0x0b, 0x67, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x08,
    0x45, 0x3a, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x08, 0xeb, 0x49, 0xe0, 0x00,
    0x00, 0x00, 0x00, 0x0a, 0x2e, 0x57, 0x70, 0x00, 0x00, 0x00, 0x00, 0x0a,
    0xcb, 0x39, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0e, 0x39, 0x70, 0x00,
    0x00, 0x00, 0x00, 0x0c, 0xab, 0x1b, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x0d,
    0xe4, 0xe0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x8a, 0xfd, 0xf0, 0x00,
    0x00, 0x00, 0x00, 0x0f, 0xcd, 0xfd, 0x70, 0x00, 0x00, 0x00, 0x00, 0x10,
    0x74, 0x1a, 0x70, 0x00, 0x00, 0x00, 0x00, 0x11, 0xad, 0xdf, 0x70, 0x00,
    0x00, 0x00, 0x00, 0x12, 0x53, 0xfc, 0x70, 0x00, 0x00, 0x00, 0x00, 0x12,
    0xce, 0x97, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x13, 0x4d, 0x44, 0x10, 0x00,
    0x00, 0x00, 0x00, 0x14, 0x33, 0xfa, 0x90, 0x00, 0x00, 0x00, 0x00, 0x15,
    0x23, 0xeb, 0x90, 0x00, 0x00, 0x00, 0x00, 0x16, 0x13, 0xdc, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x17, 0x03, 0xcd, 0x90, 0x00, 0x00, 0x00, 0x00, 0x17,
    0xf3, 0xbe, 0x90, 0x00, 0x00, 0x00, 0x00, 0x18, 0xe3, 0xaf, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x19, 0xd3, 0xa0, 0x90, 0x00, 0x00, 0x00, 0x00, 0x1a,
    0xc3, 0x91, 0x90, 0x00, 0x00, 0x00, 0x00, 0x1b, 0xbc, 0xbd, 0x10, 0x00,
    0x00, 0x00, 0x00, 0x1c, 0xac, 0xae, 0x10, 0x00, 0x00, 0x00, 0x00, 0x1d,
    0x9c, 0x9f, 0x10, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x8c, 0x90, 0x10, 0x00,
    0x00, 0x00, 0x00, 0x1f, 0x7c, 0x81, 0x10, 0x00, 0x00, 0x00, 0x00, 0x20,
    0x6c, 0x72, 0x10, 0x00, 0x00, 0x00, 0x00, 0x21, 0x5c, 0x63, 0x10, 0x00,
    0x00, 0x00, 0x00, 0x22, 0x4c, 0x54, 0x10, 0x00, 0x00, 0x00, 0x00, 0x23,
    0x3c, 0x45, 0x10, 0x00, 0x00, 0x00, 0x00, 0x24, 0x2c, 0x36, 0x10, 0x00,
    0x00, 0x00, 0x00, 0x25, 0x1c, 0x27, 0x10, 0x00, 0x00, 0x00, 0x00, 0x26,
    0x0c, 0x18, 0x10, 0x00, 0x00, 0x00, 0x00, 0x27, 0x05, 0x43, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x27, 0xf5, 0x34, 0x90, 0x00, 0x00, 0x00, 0x00, 0x28,
    0xe5, 0x25, 0x90, 0x00, 0x00, 0x00, 0x00, 0x29, 0xd5, 0x16, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x2a, 0xc5, 0x07, 0x90, 0x00, 0x00, 0x00, 0x00, 0x2b,
    0xb4, 0xf8, 0x90, 0x00, 0x00, 0x00, 0x00, 0x2c, 0xa4, 0xe9, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x2d, 0x94, 0xda, 0x90, 0x00, 0x00, 0x00, 0x00, 0x2e,
    0x84, 0xcb, 0x90, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x74, 0xbc, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x30, 0x64, 0xad, 0x90, 0x00, 0x00, 0x00, 0x00, 0x31,
    0x5d, 0xd9, 0x10, 0x00, 0x00, 0x00, 0x00, 0x32, 0x72, 0xb4, 0x10, 0x00,
    0x00, 0x00, 0x00, 0x33, 0x3d, 0xbb, 0x10, 0x00, 0x00, 0x00, 0x00, 0x34,
    0x52, 0x96, 0x10, 0x00, 0x00, 0x00, 0x00, 0x35, 0x1d, 0x9d, 0x10, 0x00,
    0x00, 0x00, 0x00, 0x36, 0x32, 0x78, 0x10, 0x00, 0x00, 0x00, 0x00, 0x36,
    0xfd, 0x7f, 0x10, 0x00, 0x00, 0x00, 0x00, 0x38, 0x1b, 0x94, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x38, 0xdd, 0x61, 0x10, 0x00, 0x00, 0x00, 0x00, 0x39,
    0xfb, 0x76, 0x90, 0x00, 0x00, 0x00, 0x00, 0x3a, 0xbd, 0x43, 0x10, 0x00,
    0x00, 0x00, 0x00, 0x3b, 0xdb, 0x58, 0x90, 0x00, 0x00, 0x00, 0x00, 0x3c,
    0xa6, 0x5f, 0x90, 0x00, 0x00, 0x00, 0x00, 0x3d, 0xbb, 0x3a, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x3e, 0x86, 0x41, 0x90, 0x00, 0x00, 0x00, 0x00, 0x3f,
    0x9b, 0x1c, 0x90, 0x00, 0x00, 0x00, 0x00, 0x40, 0x66, 0x23, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x41, 0x84, 0x39, 0x10, 0x00, 0x00, 0x00, 0x00, 0x42,
    0x46, 0x05, 0x90, 0x00, 0x00, 0x00, 0x00, 0x43, 0x64, 0x1b, 0x10, 0x00,
    0x00, 0x00, 0x00, 0x44, 0x25, 0xe7, 0x90, 0x00, 0x00, 0x00, 0x00, 0x45,
    0x43, 0xfd, 0x10, 0x00, 0x00, 0x00, 0x00, 0x46, 0x05, 0xc9, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x47, 0x23, 0xdf, 0x10, 0x00, 0x00, 0x00, 0x00, 0x47,
    0xee, 0xe6, 0x10, 0x00, 0x00, 0x00, 0x00, 0x49, 0x03, 0xc1, 0x10, 0x00,
    0x00, 0x00, 0x00, 0x49, 0xce, 0xc8, 0x10, 0x00, 0x00, 0x00, 0x00, 0x4a,
    0xe3, 0xa3, 0x10, 0x00, 0x00, 0x00, 0x00, 0x4b, 0xae, 0xaa, 0x10, 0x00,
    0x00, 0x00, 0x00, 0x4c, 0xcc, 0xbf, 0x90, 0x00, 0x00, 0x00, 0x00, 0x4d,
    0x8e, 0x8c, 0x10, 0x00, 0x00, 0x00, 0x00, 0x4e, 0xac, 0xa1, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x4f, 0x6e, 0x6e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x50,
    0x8c, 0x83, 0x90, 0x00, 0x00, 0x00, 0x00, 0x51, 0x57, 0x8a, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x52, 0x6c, 0x65, 0x90, 0x00, 0x00, 0x00, 0x00, 0x53,
    0x37, 0x6c, 0x90, 0x00, 0x00, 0x00, 0x00, 0x54, 0x4c, 0x47, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x55, 0x17, 0x4e, 0x90, 0x00, 0x00, 0x00, 0x00, 0x56,
    0x2c, 0x29, 0x90, 0x00, 0x00, 0x00, 0x00, 0x56, 0xf7, 0x30, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x58, 0x15, 0x46, 0x10, 0x00, 0x00, 0x00, 0x00, 0x58,
    0xd7, 0x12, 0x90, 0x00, 0x00, 0x00, 0x00, 0x59, 0xf5, 0x28, 0x10, 0x00,
    0x00, 0x00, 0x00, 0x5a, 0xb6, 0xf4, 0x90, 0x00, 0x00, 0x00, 0x00, 0x5b,
    0xd5, 0x0a, 0x10, 0x00, 0x00, 0x00, 0x00, 0x5c, 0xa0, 0x11, 0x10, 0x00,
    0x00, 0x00, 0x00, 0x5d, 0xb4, 0xec, 0x10, 0x00, 0x00, 0x00, 0x00, 0x5e,
    0x7f, 0xf3, 0x10, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x94, 0xce, 0x10, 0x00,
    0x00, 0x00, 0x00, 0x60, 0x5f, 0xd5, 0x10, 0x00, 0x00, 0x00, 0x00, 0x61,
    0x7d, 0xea, 0x90, 0x00, 0x00, 0x00, 0x00, 0x62, 0x3f, 0xb7, 0x10, 0x00,
    0x00, 0x00, 0x00, 0x63, 0x5d, 0xcc, 0x90, 0x00, 0x00, 0x00, 0x00, 0x64,
    0x1f, 0x99, 0x10, 0x00, 0x00, 0x00, 0x00, 0x65, 0x3d, 0xae, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x66, 0x08, 0xb5, 0x90, 0x00, 0x00, 0x00, 0x00, 0x67,
    0x1d, 0x90, 0x90, 0x00, 0x00, 0x00, 0x00, 0x67, 0xe8, 0x97, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x68, 0xfd, 0x72, 0x90, 0x00, 0x00, 0x00, 0x00, 0x69,
    0xc8, 0x79, 0x90, 0x00, 0x00, 0x00, 0x00, 0x6a, 0xdd, 0x54, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x6b, 0xa8, 0x5b, 0x90, 0x00, 0x00, 0x00, 0x00, 0x6c,
    0xc6, 0x71, 0x10, 0x00, 0x00, 0x00, 0x00, 0x6d, 0x88, 0x3d, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x6e, 0xa6, 0x53, 0x10, 0x00, 0x00, 0x00, 0x00, 0x6f,
    0x68, 0x1f, 0x90, 0x00, 0x00, 0x00, 0x00, 0x70, 0x86, 0x35, 0x10, 0x00,
    0x00, 0x00, 0x00, 0x71, 0x51, 0x3c, 0x10, 0x00, 0x00, 0x00, 0x00, 0x72,
    0x66, 0x17, 0x10, 0x00, 0x00, 0x00, 0x00, 0x73, 0x31, 0x1e, 0x10, 0x00,
    0x00, 0x00, 0x00, 0x74, 0x45, 0xf9, 0x10, 0x00, 0x00, 0x00, 0x00, 0x75,
    0x11, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x76, 0x2f, 0x15, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x76, 0xf0, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x00, 0x78,
    0x0e, 0xf7, 0x90, 0x00, 0x00, 0x00, 0x00, 0x78, 0xd0, 0xc4, 0x10, 0x00,
    0x00, 0x00, 0x00, 0x79, 0xee, 0xd9, 0x90, 0x00, 0x00, 0x00, 0x00, 0x7a,
    0xb0, 0xa6, 0x10, 0x00, 0x00, 0x00, 0x00, 0x7b, 0xce, 0xbb, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x7c, 0x99, 0xc2, 0x90, 0x00, 0x00, 0x00, 0x00, 0x7d,
    0xae, 0x9d, 0x90, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x79, 0xa4, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x7f, 0x8e, 0x7f, 0x90, 0x01, 0x03, 0x02, 0x03, 0x02,
    0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02,
    0x04, 0x03, 0x04, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x04, 0x05,
    0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05,
    0x04, 0x05, 0x04, 0x05, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03,
    0x02, 0x03, 0x05, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06,
    0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06,
    0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06,
    0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06,
    0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06,
    0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06,
    0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06,
    0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06,
    0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06,
    0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x00,
    0x00, 0x0b, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x0b, 0xb4, 0x00, 0x04, 0x00,
    0x00, 0x1c, 0x20, 0x01, 0x08, 0x00, 0x00, 0x0e, 0x10, 0x00, 0x0d, 0x00,
    0x00, 0x1c, 0x20, 0x01, 0x08, 0x00, 0x00, 0x0e, 0x10, 0x00, 0x0d, 0x00,
    0x00, 0x1c, 0x20, 0x01, 0x08, 0x00, 0x00, 0x0e, 0x10, 0x00, 0x0d, 0x4c,
    0x4d, 0x54, 0x00, 0x52, 0x4d, 0x54, 0x00, 0x43, 0x45, 0x53, 0x54, 0x00,
    0x43, 0x45, 0x54, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x0a, 0x43, 0x45, 0x54,
    0x2d, 0x31, 0x43, 0x45, 0x53, 0x54, 0x2c, 0x4d, 0x33, 0x2e, 0x35, 0x2e,
    0x30, 0x2c, 0x4d, 0x31, 0x30, 0x2e, 0x35, 0x2e, 0x30, 0x2f, 0x33, 0x0a,
};

// Etc/GMT
static const unsigned char ETC_GMT_DATA[] = {
    0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
    0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x47, 0x4d, 0x54, 0x00, 0x00, 0x00, 0x54, 0x5a, 0x69, 0x66,
    0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
    0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x4d,
    0x54, 0x00, 0x00, 0x00, 0x0a, 0x47, 0x4d, 0x54, 0x30, 0x0a,
};

// Etc/GMT+1
static const unsigned char ETC_GMTP1_DATA[] = {
    0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
    0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0xff, 0xff, 0xf1, 0xf0,
    0x00, 0x00, 0x47, 0x4d, 0x54, 0x2b, 0x31, 0x00, 0x00, 0x00, 0x54, 0x5a,
    0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
    0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0xff, 0xff, 0xf1, 0xf0, 0x00, 0x00,
    0x47, 0x4d, 0x54, 0x2b, 0x31, 0x00, 0x00, 0x00, 0x0a, 0x3c, 0x47, 0x4d,
    0x54, 0x2b, 0x31, 0x3e, 0x31, 0x0a,
};

// Etc/GMT+2
static const unsigned char ETC_GMTP2_DATA[] = {
    0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
    0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0xff, 0xff, 0xd5, 0xd0,
    0x00, 0x00, 0x47, 0x4d, 0x54, 0x2b, 0x33, 0x00, 0x00, 0x00, 0x54, 0x5a,
    0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
    0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0xff, 0xff, 0xd5, 0xd0, 0x00, 0x00,
    0x47, 0x4d, 0x54, 0x2b, 0x33, 0x00, 0x00, 0x00, 0x0a, 0x3c, 0x47, 0x4d,
    0x54, 0x2b, 0x33, 0x3e, 0x33, 0x0a,
};

// Etc/GMT-1
static const unsigned char ETC_GMTM1_DATA[] = {
    0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
    0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x0e, 0x10,
    0x00, 0x00, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x00, 0x00, 0x00, 0x54, 0x5a,
    0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
    0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x0e, 0x10, 0x00, 0x00,
    0x47, 0x4d, 0x54, 0x2d, 0x31, 0x00, 0x00, 0x00, 0x0a, 0x3c, 0x47, 0x4d,
    0x54, 0x2d, 0x31, 0x3e, 0x2d, 0x31, 0x0a,
};

// Asia/Riyadh
static const unsigned char ASIA_RIYADH_DATA[] = {
    0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
    0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
    0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0xda, 0x61, 0x36, 0xb4,
    0x01, 0x00, 0x00, 0x2b, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x30, 0x00,
    0x04, 0x4c, 0x4d, 0x54, 0x00, 0x41, 0x53, 0x54, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0xff, 0xff, 0xff,
    0xff, 0xda, 0x61, 0x36, 0xb4, 0x01, 0x00, 0x00, 0x2b, 0xcc, 0x00, 0x00,
    0x00, 0x00, 0x2a, 0x30, 0x00, 0x04, 0x4c, 0x4d, 0x54, 0x00, 0x41, 0x53,
    0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x41, 0x53, 0x54, 0x2d, 0x33,
    0x0a,
};

// Asia/Saigon
static const unsigned char ASIA_SAIGON_DATA[] = {
    0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
    0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
    0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0c, 0x88, 0x6f, 0x42, 0x80,
    0x91, 0x5f, 0xee, 0xd0, 0x93, 0x85, 0xb1, 0x90, 0xb7, 0x41, 0xbc, 0x00,
    0x01, 0x02, 0x03, 0x02, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x63, 0xec, 0x00, 0x04, 0x00, 0x00, 0x62, 0x70, 0x00, 0x08, 0x00, 0x00,
    0x70, 0x80, 0x00, 0x08, 0x4c, 0x4d, 0x54, 0x00, 0x53, 0x4d, 0x54, 0x00,
    0x49, 0x43, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
    0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
    0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0c, 0xff, 0xff, 0xff, 0xff,
    0x88, 0x6f, 0x42, 0x80, 0xff, 0xff, 0xff, 0xff, 0x91, 0x5f, 0xee, 0xd0,
    0xff, 0xff, 0xff, 0xff, 0x93, 0x85, 0xb1, 0x90, 0xff, 0xff, 0xff, 0xff,
    0xb7, 0x41, 0xbc, 0x00, 0x01, 0x02, 0x03, 0x02, 0x00, 0x00, 0x64, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x63, 0xec, 0x00, 0x04, 0x00, 0x00, 0x62, 0x70,
    0x00, 0x08, 0x00, 0x00, 0x70, 0x80, 0x00, 0x08, 0x4c, 0x4d, 0x54, 0x00,
    0x53, 0x4d, 0x54, 0x00, 0x49, 0x43, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x0a, 0x49, 0x43, 0x54, 0x2d, 0x37, 0x0a,
};

static const unsigned char EUROPE_BERLIN_DATA[] = {
    0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
    0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90,
    0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0e, 0x9b, 0x0c, 0x17, 0x60,
    0x9b, 0xd5, 0xda, 0xf0, 0x9c, 0xd9, 0xae, 0x90, 0x9d, 0xa4, 0xb5, 0x90,
    0x9e, 0xb9, 0x90, 0x90, 0x9f, 0x84, 0x97, 0x90, 0xc8, 0x09, 0x71, 0x90,
    0xcc, 0xe7, 0x4b, 0x10, 0xcd, 0xa9, 0x17, 0x90, 0xce, 0xa2, 0x43, 0x10,
    0xcf, 0x92, 0x34, 0x10, 0xd0, 0x82, 0x25, 0x10, 0xd1, 0x72, 0x16, 0x10,
    0xd1, 0xb6, 0x96, 0x00, 0xd2, 0x58, 0xbe, 0x80, 0xd2, 0xa1, 0x4f, 0x10,
    0xd2, 0xdb, 0x34, 0xf0, 0xd3, 0x63, 0x1b, 0x90, 0xd4, 0x4b, 0x23, 0x90,
    0xd5, 0x39, 0xd1, 0x20, 0xd5, 0x67, 0xe7, 0x90, 0xd5, 0xa8, 0x73, 0x00,
    0xd6, 0x29, 0xb4, 0x10, 0xd7, 0x2c, 0x1a, 0x10, 0xd8, 0x09, 0x96, 0x10,
    0xd9, 0x02, 0xc1, 0x90, 0xd9, 0xe9, 0x78, 0x10, 0x12, 0xce, 0x97, 0xf0,
    0x13, 0x4d, 0x44, 0x10, 0x14, 0x33, 0xfa, 0x90, 0x15, 0x23, 0xeb, 0x90,
    0x16, 0x13, 0xdc, 0x90, 0x17, 0x03, 0xcd, 0x90, 0x17, 0xf3, 0xbe, 0x90,
    0x18, 0xe3, 0xaf, 0x90, 0x19, 0xd3, 0xa0, 0x90, 0x1a, 0xc3, 0x91, 0x90,
    0x1b, 0xbc, 0xbd, 0x10, 0x1c, 0xac, 0xae, 0x10, 0x1d, 0x9c, 0x9f, 0x10,
    0x1e, 0x8c, 0x90, 0x10, 0x1f, 0x7c, 0x81, 0x10, 0x20, 0x6c, 0x72, 0x10,
    0x21, 0x5c, 0x63, 0x10, 0x22, 0x4c, 0x54, 0x10, 0x23, 0x3c, 0x45, 0x10,
    0x24, 0x2c, 0x36, 0x10, 0x25, 0x1c, 0x27, 0x10, 0x26, 0x0c, 0x18, 0x10,
    0x27, 0x05, 0x43, 0x90, 0x27, 0xf5, 0x34, 0x90, 0x28, 0xe5, 0x25, 0x90,
    0x29, 0xd5, 0x16, 0x90, 0x2a, 0xc5, 0x07, 0x90, 0x2b, 0xb4, 0xf8, 0x90,
    0x2c, 0xa4, 0xe9, 0x90, 0x2d, 0x94, 0xda, 0x90, 0x2e, 0x84, 0xcb, 0x90,
    0x2f, 0x74, 0xbc, 0x90, 0x30, 0x64, 0xad, 0x90, 0x31, 0x5d, 0xd9, 0x10,
    0x32, 0x72, 0xb4, 0x10, 0x33, 0x3d, 0xbb, 0x10, 0x34, 0x52, 0x96, 0x10,
    0x35, 0x1d, 0x9d, 0x10, 0x36, 0x32, 0x78, 0x10, 0x36, 0xfd, 0x7f, 0x10,
    0x38, 0x1b, 0x94, 0x90, 0x38, 0xdd, 0x61, 0x10, 0x39, 0xfb, 0x76, 0x90,
    0x3a, 0xbd, 0x43, 0x10, 0x3b, 0xdb, 0x58, 0x90, 0x3c, 0xa6, 0x5f, 0x90,
    0x3d, 0xbb, 0x3a, 0x90, 0x3e, 0x86, 0x41, 0x90, 0x3f, 0x9b, 0x1c, 0x90,
    0x40, 0x66, 0x23, 0x90, 0x41, 0x84, 0x39, 0x10, 0x42, 0x46, 0x05, 0x90,
    0x43, 0x64, 0x1b, 0x10, 0x44, 0x25, 0xe7, 0x90, 0x45, 0x43, 0xfd, 0x10,
    0x46, 0x05, 0xc9, 0x90, 0x47, 0x23, 0xdf, 0x10, 0x47, 0xee, 0xe6, 0x10,
    0x49, 0x03, 0xc1, 0x10, 0x49, 0xce, 0xc8, 0x10, 0x4a, 0xe3, 0xa3, 0x10,
    0x4b, 0xae, 0xaa, 0x10, 0x4c, 0xcc, 0xbf, 0x90, 0x4d, 0x8e, 0x8c, 0x10,
    0x4e, 0xac, 0xa1, 0x90, 0x4f, 0x6e, 0x6e, 0x10, 0x50, 0x8c, 0x83, 0x90,
    0x51, 0x57, 0x8a, 0x90, 0x52, 0x6c, 0x65, 0x90, 0x53, 0x37, 0x6c, 0x90,
    0x54, 0x4c, 0x47, 0x90, 0x55, 0x17, 0x4e, 0x90, 0x56, 0x2c, 0x29, 0x90,
    0x56, 0xf7, 0x30, 0x90, 0x58, 0x15, 0x46, 0x10, 0x58, 0xd7, 0x12, 0x90,
    0x59, 0xf5, 0x28, 0x10, 0x5a, 0xb6, 0xf4, 0x90, 0x5b, 0xd5, 0x0a, 0x10,
    0x5c, 0xa0, 0x11, 0x10, 0x5d, 0xb4, 0xec, 0x10, 0x5e, 0x7f, 0xf3, 0x10,
    0x5f, 0x94, 0xce, 0x10, 0x60, 0x5f, 0xd5, 0x10, 0x61, 0x7d, 0xea, 0x90,
    0x62, 0x3f, 0xb7, 0x10, 0x63, 0x5d, 0xcc, 0x90, 0x64, 0x1f, 0x99, 0x10,
    0x65, 0x3d, 0xae, 0x90, 0x66, 0x08, 0xb5, 0x90, 0x67, 0x1d, 0x90, 0x90,
    0x67, 0xe8, 0x97, 0x90, 0x68, 0xfd, 0x72, 0x90, 0x69, 0xc8, 0x79, 0x90,
    0x6a, 0xdd, 0x54, 0x90, 0x6b, 0xa8, 0x5b, 0x90, 0x6c, 0xc6, 0x71, 0x10,
    0x6d, 0x88, 0x3d, 0x90, 0x6e, 0xa6, 0x53, 0x10, 0x6f, 0x68, 0x1f, 0x90,
    0x70, 0x86, 0x35, 0x10, 0x71, 0x51, 0x3c, 0x10, 0x72, 0x66, 0x17, 0x10,
    0x73, 0x31, 0x1e, 0x10, 0x74, 0x45, 0xf9, 0x10, 0x75, 0x11, 0x00, 0x10,
    0x76, 0x2f, 0x15, 0x90, 0x76, 0xf0, 0xe2, 0x10, 0x78, 0x0e, 0xf7, 0x90,
    0x78, 0xd0, 0xc4, 0x10, 0x79, 0xee, 0xd9, 0x90, 0x7a, 0xb0, 0xa6, 0x10,
    0x7b, 0xce, 0xbb, 0x90, 0x7c, 0x99, 0xc2, 0x90, 0x7d, 0xae, 0x9d, 0x90,
    0x7e, 0x79, 0xa4, 0x90, 0x7f, 0x8e, 0x7f, 0x90, 0x00, 0x01, 0x02, 0x03,
    0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x04, 0x00, 0x03,
    0x01, 0x02, 0x03, 0x02, 0x05, 0x00, 0x03, 0x02, 0x03, 0x02, 0x03, 0x01,
    0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07,
    0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07,
    0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07,
    0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07,
    0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07,
    0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07,
    0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07,
    0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07,
    0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07,
    0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x00, 0x00, 0x1c, 0x20,
    0x01, 0x00, 0x00, 0x00, 0x0e, 0x10, 0x00, 0x05, 0x00, 0x00, 0x1c, 0x20,
    0x01, 0x00, 0x00, 0x00, 0x0e, 0x10, 0x00, 0x05, 0x00, 0x00, 0x2a, 0x30,
    0x01, 0x09, 0x00, 0x00, 0x2a, 0x30, 0x01, 0x09, 0x00, 0x00, 0x1c, 0x20,
    0x01, 0x00, 0x00, 0x00, 0x0e, 0x10, 0x00, 0x05, 0x43, 0x45, 0x53, 0x54,
    0x00, 0x43, 0x45, 0x54, 0x00, 0x43, 0x45, 0x4d, 0x54, 0x00, 0x00, 0x00,
    0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x01, 0x01, 0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x91, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x12, 0xff, 0xff,
    0xff, 0xff, 0x6f, 0xa2, 0x61, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x9b, 0x0c,
    0x17, 0x60, 0xff, 0xff, 0xff, 0xff, 0x9b, 0xd5, 0xda, 0xf0, 0xff, 0xff,
    0xff, 0xff, 0x9c, 0xd9, 0xae, 0x90, 0xff, 0xff, 0xff, 0xff, 0x9d, 0xa4,
    0xb5, 0x90, 0xff, 0xff, 0xff, 0xff, 0x9e, 0xb9, 0x90, 0x90, 0xff, 0xff,
    0xff, 0xff, 0x9f, 0x84, 0x97, 0x90, 0xff, 0xff, 0xff, 0xff, 0xc8, 0x09,
    0x71, 0x90, 0xff, 0xff, 0xff, 0xff, 0xcc, 0xe7, 0x4b, 0x10, 0xff, 0xff,
    0xff, 0xff, 0xcd, 0xa9, 0x17, 0x90, 0xff, 0xff, 0xff, 0xff, 0xce, 0xa2,
    0x43, 0x10, 0xff, 0xff, 0xff, 0xff, 0xcf, 0x92, 0x34, 0x10, 0xff, 0xff,
    0xff, 0xff, 0xd0, 0x82, 0x25, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd1, 0x72,
    0x16, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd1, 0xb6, 0x96, 0x00, 0xff, 0xff,
    0xff, 0xff, 0xd2, 0x58, 0xbe, 0x80, 0xff, 0xff, 0xff, 0xff, 0xd2, 0xa1,
    0x4f, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd2, 0xdb, 0x34, 0xf0, 0xff, 0xff,
    0xff, 0xff, 0xd3, 0x63, 0x1b, 0x90, 0xff, 0xff, 0xff, 0xff, 0xd4, 0x4b,
    0x23, 0x90, 0xff, 0xff, 0xff, 0xff, 0xd5, 0x39, 0xd1, 0x20, 0xff, 0xff,
    0xff, 0xff, 0xd5, 0x67, 0xe7, 0x90, 0xff, 0xff, 0xff, 0xff, 0xd5, 0xa8,
    0x73, 0x00, 0xff, 0xff, 0xff, 0xff, 0xd6, 0x29, 0xb4, 0x10, 0xff, 0xff,
    0xff, 0xff, 0xd7, 0x2c, 0x1a, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd8, 0x09,
    0x96, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd9, 0x02, 0xc1, 0x90, 0xff, 0xff,
    0xff, 0xff, 0xd9, 0xe9, 0x78, 0x10, 0x00, 0x00, 0x00, 0x00, 0x12, 0xce,
    0x97, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x13, 0x4d, 0x44, 0x10, 0x00, 0x00,
    0x00, 0x00, 0x14, 0x33, 0xfa, 0x90, 0x00, 0x00, 0x00, 0x00, 0x15, 0x23,
    0xeb, 0x90, 0x00, 0x00, 0x00, 0x00, 0x16, 0x13, 0xdc, 0x90, 0x00, 0x00,
    0x00, 0x00, 0x17, 0x03, 0xcd, 0x90, 0x00, 0x00, 0x00, 0x00, 0x17, 0xf3,
    0xbe, 0x90, 0x00, 0x00, 0x00, 0x00, 0x18, 0xe3, 0xaf, 0x90, 0x00, 0x00,
    0x00, 0x00, 0x19, 0xd3, 0xa0, 0x90, 0x00, 0x00, 0x00, 0x00, 0x1a, 0xc3,
    0x91, 0x90, 0x00, 0x00, 0x00, 0x00, 0x1b, 0xbc, 0xbd, 0x10, 0x00, 0x00,
    0x00, 0x00, 0x1c, 0xac, 0xae, 0x10, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x9c,
    0x9f, 0x10, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x8c, 0x90, 0x10, 0x00, 0x00,
    0x00, 0x00, 0x1f, 0x7c, 0x81, 0x10, 0x00, 0x00, 0x00, 0x00, 0x20, 0x6c,
    0x72, 0x10, 0x00, 0x00, 0x00, 0x00, 0x21, 0x5c, 0x63, 0x10, 0x00, 0x00,
    0x00, 0x00, 0x22, 0x4c, 0x54, 0x10, 0x00, 0x00, 0x00, 0x00, 0x23, 0x3c,
    0x45, 0x10, 0x00, 0x00, 0x00, 0x00, 0x24, 0x2c, 0x36, 0x10, 0x00, 0x00,
    0x00, 0x00, 0x25, 0x1c, 0x27, 0x10, 0x00, 0x00, 0x00, 0x00, 0x26, 0x0c,
    0x18, 0x10, 0x00, 0x00, 0x00, 0x00, 0x27, 0x05, 0x43, 0x90, 0x00, 0x00,
    0x00, 0x00, 0x27, 0xf5, 0x34, 0x90, 0x00, 0x00, 0x00, 0x00, 0x28, 0xe5,
    0x25, 0x90, 0x00, 0x00, 0x00, 0x00, 0x29, 0xd5, 0x16, 0x90, 0x00, 0x00,
    0x00, 0x00, 0x2a, 0xc5, 0x07, 0x90, 0x00, 0x00, 0x00, 0x00, 0x2b, 0xb4,
    0xf8, 0x90, 0x00, 0x00, 0x00, 0x00, 0x2c, 0xa4, 0xe9, 0x90, 0x00, 0x00,
    0x00, 0x00, 0x2d, 0x94, 0xda, 0x90, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x84,
    0xcb, 0x90, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x74, 0xbc, 0x90, 0x00, 0x00,
    0x00, 0x00, 0x30, 0x64, 0xad, 0x90, 0x00, 0x00, 0x00, 0x00, 0x31, 0x5d,
    0xd9, 0x10, 0x00, 0x00, 0x00, 0x00, 0x32, 0x72, 0xb4, 0x10, 0x00, 0x00,
    0x00, 0x00, 0x33, 0x3d, 0xbb, 0x10, 0x00, 0x00, 0x00, 0x00, 0x34, 0x52,
    0x96, 0x10, 0x00, 0x00, 0x00, 0x00, 0x35, 0x1d, 0x9d, 0x10, 0x00, 0x00,
    0x00, 0x00, 0x36, 0x32, 0x78, 0x10, 0x00, 0x00, 0x00, 0x00, 0x36, 0xfd,
    0x7f, 0x10, 0x00, 0x00, 0x00, 0x00, 0x38, 0x1b, 0x94, 0x90, 0x00, 0x00,
    0x00, 0x00, 0x38, 0xdd, 0x61, 0x10, 0x00, 0x00, 0x00, 0x00, 0x39, 0xfb,
    0x76, 0x90, 0x00, 0x00, 0x00, 0x00, 0x3a, 0xbd, 0x43, 0x10, 0x00, 0x00,
    0x00, 0x00, 0x3b, 0xdb, 0x58, 0x90, 0x00, 0x00, 0x00, 0x00, 0x3c, 0xa6,
    0x5f, 0x90, 0x00, 0x00, 0x00, 0x00, 0x3d, 0xbb, 0x3a, 0x90, 0x00, 0x00,
    0x00, 0x00, 0x3e, 0x86, 0x41, 0x90, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x9b,
    0x1c, 0x90, 0x00, 0x00, 0x00, 0x00, 0x40, 0x66, 0x23, 0x90, 0x00, 0x00,
    0x00, 0x00, 0x41, 0x84, 0x39, 0x10, 0x00, 0x00, 0x00, 0x00, 0x42, 0x46,
    0x05, 0x90, 0x00, 0x00, 0x00, 0x00, 0x43, 0x64, 0x1b, 0x10, 0x00, 0x00,
    0x00, 0x00, 0x44, 0x25, 0xe7, 0x90, 0x00, 0x00, 0x00, 0x00, 0x45, 0x43,
    0xfd, 0x10, 0x00, 0x00, 0x00, 0x00, 0x46, 0x05, 0xc9, 0x90, 0x00, 0x00,
    0x00, 0x00, 0x47, 0x23, 0xdf, 0x10, 0x00, 0x00, 0x00, 0x00, 0x47, 0xee,
    0xe6, 0x10, 0x00, 0x00, 0x00, 0x00, 0x49, 0x03, 0xc1, 0x10, 0x00, 0x00,
    0x00, 0x00, 0x49, 0xce, 0xc8, 0x10, 0x00, 0x00, 0x00, 0x00, 0x4a, 0xe3,
    0xa3, 0x10, 0x00, 0x00, 0x00, 0x00, 0x4b, 0xae, 0xaa, 0x10, 0x00, 0x00,
    0x00, 0x00, 0x4c, 0xcc, 0xbf, 0x90, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x8e,
    0x8c, 0x10, 0x00, 0x00, 0x00, 0x00, 0x4e, 0xac, 0xa1, 0x90, 0x00, 0x00,
    0x00, 0x00, 0x4f, 0x6e, 0x6e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x50, 0x8c,
    0x83, 0x90, 0x00, 0x00, 0x00, 0x00, 0x51, 0x57, 0x8a, 0x90, 0x00, 0x00,
    0x00, 0x00, 0x52, 0x6c, 0x65, 0x90, 0x00, 0x00, 0x00, 0x00, 0x53, 0x37,
    0x6c, 0x90, 0x00, 0x00, 0x00, 0x00, 0x54, 0x4c, 0x47, 0x90, 0x00, 0x00,
    0x00, 0x00, 0x55, 0x17, 0x4e, 0x90, 0x00, 0x00, 0x00, 0x00, 0x56, 0x2c,
    0x29, 0x90, 0x00, 0x00, 0x00, 0x00, 0x56, 0xf7, 0x30, 0x90, 0x00, 0x00,
    0x00, 0x00, 0x58, 0x15, 0x46, 0x10, 0x00, 0x00, 0x00, 0x00, 0x58, 0xd7,
    0x12, 0x90, 0x00, 0x00, 0x00, 0x00, 0x59, 0xf5, 0x28, 0x10, 0x00, 0x00,
    0x00, 0x00, 0x5a, 0xb6, 0xf4, 0x90, 0x00, 0x00, 0x00, 0x00, 0x5b, 0xd5,
    0x0a, 0x10, 0x00, 0x00, 0x00, 0x00, 0x5c, 0xa0, 0x11, 0x10, 0x00, 0x00,
    0x00, 0x00, 0x5d, 0xb4, 0xec, 0x10, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x7f,
    0xf3, 0x10, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x94, 0xce, 0x10, 0x00, 0x00,
    0x00, 0x00, 0x60, 0x5f, 0xd5, 0x10, 0x00, 0x00, 0x00, 0x00, 0x61, 0x7d,
    0xea, 0x90, 0x00, 0x00, 0x00, 0x00, 0x62, 0x3f, 0xb7, 0x10, 0x00, 0x00,
    0x00, 0x00, 0x63, 0x5d, 0xcc, 0x90, 0x00, 0x00, 0x00, 0x00, 0x64, 0x1f,
    0x99, 0x10, 0x00, 0x00, 0x00, 0x00, 0x65, 0x3d, 0xae, 0x90, 0x00, 0x00,
    0x00, 0x00, 0x66, 0x08, 0xb5, 0x90, 0x00, 0x00, 0x00, 0x00, 0x67, 0x1d,
    0x90, 0x90, 0x00, 0x00, 0x00, 0x00, 0x67, 0xe8, 0x97, 0x90, 0x00, 0x00,
    0x00, 0x00, 0x68, 0xfd, 0x72, 0x90, 0x00, 0x00, 0x00, 0x00, 0x69, 0xc8,
    0x79, 0x90, 0x00, 0x00, 0x00, 0x00, 0x6a, 0xdd, 0x54, 0x90, 0x00, 0x00,
    0x00, 0x00, 0x6b, 0xa8, 0x5b, 0x90, 0x00, 0x00, 0x00, 0x00, 0x6c, 0xc6,
    0x71, 0x10, 0x00, 0x00, 0x00, 0x00, 0x6d, 0x88, 0x3d, 0x90, 0x00, 0x00,
    0x00, 0x00, 0x6e, 0xa6, 0x53, 0x10, 0x00, 0x00, 0x00, 0x00, 0x6f, 0x68,
    0x1f, 0x90, 0x00, 0x00, 0x00, 0x00, 0x70, 0x86, 0x35, 0x10, 0x00, 0x00,
    0x00, 0x00, 0x71, 0x51, 0x3c, 0x10, 0x00, 0x00, 0x00, 0x00, 0x72, 0x66,
    0x17, 0x10, 0x00, 0x00, 0x00, 0x00, 0x73, 0x31, 0x1e, 0x10, 0x00, 0x00,
    0x00, 0x00, 0x74, 0x45, 0xf9, 0x10, 0x00, 0x00, 0x00, 0x00, 0x75, 0x11,
    0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x76, 0x2f, 0x15, 0x90, 0x00, 0x00,
    0x00, 0x00, 0x76, 0xf0, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0e,
    0xf7, 0x90, 0x00, 0x00, 0x00, 0x00, 0x78, 0xd0, 0xc4, 0x10, 0x00, 0x00,
    0x00, 0x00, 0x79, 0xee, 0xd9, 0x90, 0x00, 0x00, 0x00, 0x00, 0x7a, 0xb0,
    0xa6, 0x10, 0x00, 0x00, 0x00, 0x00, 0x7b, 0xce, 0xbb, 0x90, 0x00, 0x00,
    0x00, 0x00, 0x7c, 0x99, 0xc2, 0x90, 0x00, 0x00, 0x00, 0x00, 0x7d, 0xae,
    0x9d, 0x90, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x79, 0xa4, 0x90, 0x00, 0x00,
    0x00, 0x00, 0x7f, 0x8e, 0x7f, 0x90, 0x02, 0x01, 0x02, 0x03, 0x04, 0x03,
    0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x05, 0x01, 0x04, 0x02,
    0x03, 0x04, 0x03, 0x06, 0x01, 0x04, 0x03, 0x04, 0x03, 0x04, 0x02, 0x07,
    0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07,
    0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07,
    0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07,
    0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07,
    0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07,
    0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07,
    0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07,
    0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07,
    0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07,
    0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x00, 0x00, 0x0c, 0x88, 0x00,
    0x00, 0x00, 0x00, 0x1c, 0x20, 0x01, 0x04, 0x00, 0x00, 0x0e, 0x10, 0x00,
    0x09, 0x00, 0x00, 0x1c, 0x20, 0x01, 0x04, 0x00, 0x00, 0x0e, 0x10, 0x00,
    0x09, 0x00, 0x00, 0x2a, 0x30, 0x01, 0x0d, 0x00, 0x00, 0x2a, 0x30, 0x01,
    0x0d, 0x00, 0x00, 0x1c, 0x20, 0x01, 0x04, 0x00, 0x00, 0x0e, 0x10, 0x00,
    0x09, 0x4c, 0x4d, 0x54, 0x00, 0x43, 0x45, 0x53, 0x54, 0x00, 0x43, 0x45,
    0x54, 0x00, 0x43, 0x45, 0x4d, 0x54, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
    0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
    0x01, 0x0a, 0x43, 0x45, 0x54, 0x2d, 0x31, 0x43, 0x45, 0x53, 0x54, 0x2c,
    0x4d, 0x33, 0x2e, 0x35, 0x2e, 0x30, 0x2c, 0x4d, 0x31, 0x30, 0x2e, 0x35,
    0x2e, 0x30, 0x2f, 0x33, 0x0a
};

// ============================================================================
//                        GLOBAL CLASSES FOR TESTING
// ----------------------------------------------------------------------------

/// The Logger verbosity guard disables logging on construction, and
/// re-enables logging, based on the prior default pass-through level, when
/// it goes out of scope and is destroyed.  It is intended to suppress
/// logged output for intentional errors when the test driver is run in
/// non-verbose mode.
struct LogVerbosityGuard {

    bool                    d_verbose;             // verbose mode does not
                                                   // disable logging

    bsls::LogSeverity::Enum d_defaultPassthrough;  // default passthrough
                                                   // log level

    /// If the optionally specified `verbose` is `false` disable logging
    /// until this guard is destroyed.
    explicit LogVerbosityGuard(bool verbose = false)
    {
        d_verbose            = verbose;
        d_defaultPassthrough = bsls::Log::severityThreshold();

        if (!d_verbose) {
            bsls::Log::setSeverityThreshold(bsls::LogSeverity::e_FATAL);
        }
    }

    /// Set the logging verbosity back to its default state.
    ~LogVerbosityGuard()
    {
        if (!d_verbose) {
            bsls::Log::setSeverityThreshold(d_defaultPassthrough);
        }
    }
};

// ============================================================================
//                             HELPER FUNCTIONS
// ----------------------------------------------------------------------------

struct ThreadArg {
    bsls::Types::Int64  d_offset;
    bdlt::Datetime      d_utcDatetime;
    bslmt::Barrier     *d_barrier_p;
};

typedef bsl::vector<struct ThreadArg> ThreadArgs;

extern "C" void *workerThread(void *arg)
{
    ThreadArg *p = static_cast<ThreadArg *>(arg);

    p->d_barrier_p->wait();

    p->d_offset = baltzo::LocalTimeOffsetUtil::localTimeOffset(
                                              p->d_utcDatetime).totalSeconds();
    return 0;
}

typedef bsl::vector<bslmt::ThreadUtil::Handle> Handles;

/// Return the interval in seconds from UNIX epoch time of the specified
/// `value`.  Note that this method is shorthand for
/// `bdlt::EpochUtil::convertToTimeT64`.
bdlt::EpochUtil::TimeT64 toTimeT(const bdlt::Datetime& value)
{
    return bdlt::EpochUtil::convertToTimeT64(value);
}

/// Return the datetime value indicated by the specified
/// `iso8601TimeString`.  The behavior is undefined unless
/// `iso8601TimeString` is a null-terminated C-string containing a time
/// description matching the iso8601 specification (see `bdlt_iso8601util`).
bdlt::Datetime toDatetime(const char *iso8601TimeString)
{
    bdlt::Datetime time;
    BSLA_MAYBE_UNUSED int rc = bdlt::Iso8601Util::parse(
                             &time,
                             iso8601TimeString,
                             static_cast<int>(bsl::strlen(iso8601TimeString)));
    BSLS_ASSERT(0 == rc);
    return time;
}

/// A `struct` describing a transitions.  Note that this type is meant to
/// be used to create data tables for use with `addTransitions`.
struct TransitionDescription {

    int         d_line;
    const char *d_transitionTime;
    int         d_offsetMins;
    const char *d_abbrev;
    bool        d_isDst;
};

/// Insert to the specified `result` the contiguous sequence of specified
/// `descriptions`, of length `numDescriptions`.
void addTransitions(baltzo::Zoneinfo            *result,
                    const TransitionDescription *descriptions,
                    int                          numDescriptions)
{
    BSLS_ASSERT(result);

    for (int i = 0; i < numDescriptions; ++i) {
        const char *TRANS = descriptions[i].d_transitionTime;
        baltzo::LocalTimeDescriptor desc(descriptions[i].d_offsetMins * 60,
                                        descriptions[i].d_isDst,
                                        descriptions[i].d_abbrev);
        result->addTransition(toTimeT(toDatetime(TRANS)), desc);
    }
}

// ============================================================================
//                               USAGE EXAMPLE
// ----------------------------------------------------------------------------

namespace UsageExample1 {
//
///Usage
///-----
// This section illustrates intended use of this component.
//
///Example 1: Using `localTimeOffset` as the Local Time Offset Callback
/// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Suppose we must quickly generate time stamp values in local time (e.g., on
// records for a high frequency logger) and the default performance of the
// relevant methods of `bdlt::CurrentTime` is inadequate.  Further suppose that
// we must do so arbitrary time values and time zones.  Those requirements can
// be met by installing the `localTimeOffset` method of
// `baltzo::LocalTimeOffsetUtil` as the local time callback used by
// `bdlt::CurrentTime`.
//
// First, specify the time zone to be used by the callback and a UTC date time
// for the initial offset information in the cache.
// ```
void main1()
{
    ASSERT(0 == baltzo::LocalTimeOffsetUtil::updateCount());

    int status = baltzo::LocalTimeOffsetUtil::configure("America/New_York",
                                                        bdlt::Datetime(2013,
                                                                         2,
                                                                        26));
    ASSERT(0 == status);
    ASSERT(1 == baltzo::LocalTimeOffsetUtil::updateCount());

    bsl::string timezone;

    baltzo::LocalTimeOffsetUtil::loadTimezone(&timezone);
    ASSERT(0 == strcmp("America/New_York", timezone.c_str()));
// ```
// Notice that the value returned by the `updateCount` method is increased by
// one after then time zone information has been set.
//
// Then, use the `setLoadLocalTimeOffsetCallback` method to set the
// `localTimeOffset` of `baltzo::LocalTimeOffsetUtil` as the local time
// offset callback used in `bdlt::CurrentTime`.
// ```
    bdlt::LocalTimeOffset::LocalTimeOffsetCallback previousCallback =
                 baltzo::LocalTimeOffsetUtil::setLoadLocalTimeOffsetCallback();

    ASSERT(&baltzo::LocalTimeOffsetUtil::localTimeOffset
        == bdlt::LocalTimeOffset::localTimeOffsetCallback());
// ```
// Notice that previously installed callback was saved so we can restore it, if
// needed.
//
// Now, calls to `bdlt::CurrentTime` methods will use the method we installed.
// For example, we can check the time offset in New York for three dates of
// interest:
// ```
    bsls::Types::Int64 offsetInSeconds =
        bdlt::LocalTimeOffset::localTimeOffset(bdlt::Datetime(2013, 2, 26))
                                                               .totalSeconds();
    ASSERT(        0 == status);
    ASSERT(-5 * 3600 == offsetInSeconds);
    ASSERT(        1 == baltzo::LocalTimeOffsetUtil::updateCount());

    baltzo::LocalTimeOffsetUtil::loadTimezone(&timezone);
    ASSERT(        0 == strcmp("America/New_York", timezone.c_str()));

    offsetInSeconds =
        bdlt::LocalTimeOffset::localTimeOffset(bdlt::Datetime(2013, 7, 4))
                                                               .totalSeconds();
    ASSERT(-4 * 3600 == offsetInSeconds);
    ASSERT(        2 == baltzo::LocalTimeOffsetUtil::updateCount());
    baltzo::LocalTimeOffsetUtil::loadTimezone(&timezone);
    ASSERT(        0 == strcmp("America/New_York", timezone.c_str()));

    offsetInSeconds =
        bdlt::LocalTimeOffset::localTimeOffset(bdlt::Datetime(2013, 12, 21))
                                                               .totalSeconds();
    ASSERT(-5 * 3600 == offsetInSeconds);
    ASSERT(        3 == baltzo::LocalTimeOffsetUtil::updateCount());
    baltzo::LocalTimeOffsetUtil::loadTimezone(&timezone);
    ASSERT(        0 == strcmp("America/New_York", timezone.c_str()));
// ```
// Notice that the value returned by `updateCount()` is unchanged by our first
// request, but incremented by the second and third request, which transitions
// into and then out of daylight saving time.  Also notice that the updates
// change the offset information but do not change the timezone.
//
// Finally, we restore the original local time callback.
// ```
    previousCallback = bdlt::LocalTimeOffset::setLocalTimeOffsetCallback(
                                                             previousCallback);
    ASSERT(previousCallback == &baltzo::LocalTimeOffsetUtil::localTimeOffset);
// ```
}
}  // close namespace UsageExample1

// ============================================================================
//                               MAIN PROGRAM
// ----------------------------------------------------------------------------

int main(int argc, char *argv[])
{
    int                 test = argc > 1 ? atoi(argv[1]) : 0;
    bool             verbose = argc > 2;
    bool         veryVerbose = argc > 3;
    bool     veryVeryVerbose = argc > 4;
    bool veryVeryVeryVerbose = argc > 5;

                g_verbose =             verbose;
            g_veryVerbose =         veryVerbose;
        g_veryVeryVerbose =     veryVeryVerbose;
    g_veryVeryVeryVerbose = veryVeryVeryVerbose;

    cout << "TEST " << __FILE__ << " CASE " << test << endl;

    // CONCERN: `BSLS_REVIEW` failures should lead to test failures.
    bsls::ReviewFailureHandlerGuard reviewGuard(&bsls::Review::failByAbort);

    bslma::TestAllocator allocator("Test", veryVeryVeryVerbose);
    bslma::TestAllocator defaultAllocator("Default", veryVeryVeryVerbose);
    bslma::DefaultAllocatorGuard guard(&defaultAllocator);
    bslma::TestAllocator *Z = &allocator;

    baltzo::TestLoader     testLoader(Z);
    baltzo::ZoneinfoCache  testCache(&testLoader, Z);
    ASSERT(0 == testLoader.setTimeZone("GMT",
                         reinterpret_cast<const char *>(GMT_DATA),
                         sizeof(GMT_DATA)));
    ASSERT(0 == testLoader.setTimeZone("Etc/GMT",
                         reinterpret_cast<const char *>(ETC_GMT_DATA),
                         sizeof(ETC_GMT_DATA)));
    ASSERT(0 == testLoader.setTimeZone("Etc/GMT+1",
                         reinterpret_cast<const char *>(ETC_GMTP1_DATA),
                         sizeof(ETC_GMTP1_DATA)));
    ASSERT(0 == testLoader.setTimeZone("Etc/GMT+2",
                         reinterpret_cast<const char *>(ETC_GMTP2_DATA),
                         sizeof(ETC_GMTP2_DATA)));
    ASSERT(0 == testLoader.setTimeZone("Etc/GMT-1",
                         reinterpret_cast<const char *>(ETC_GMTM1_DATA),
                         sizeof(ETC_GMTM1_DATA)));
    ASSERT(0 == testLoader.setTimeZone("America/New_York",
                         reinterpret_cast<const char *>(AMERICA_NEW_YORK_DATA),
                         sizeof(AMERICA_NEW_YORK_DATA)));
    ASSERT(0 == testLoader.setTimeZone("Asia/Riyadh",
                         reinterpret_cast<const char *>(ASIA_RIYADH_DATA),
                         sizeof(ASIA_RIYADH_DATA)));
    ASSERT(0 == testLoader.setTimeZone("Asia/Saigon",
                         reinterpret_cast<const char *>(ASIA_SAIGON_DATA),
                         sizeof(ASIA_SAIGON_DATA)));
    ASSERT(0 == testLoader.setTimeZone("Europe/Rome",
                         reinterpret_cast<const char *>(EUROPE_ROME_DATA),
                         sizeof(EUROPE_ROME_DATA)));
    ASSERT(0 == testLoader.setTimeZone("Europe/Berlin",
                         reinterpret_cast<const char *>(EUROPE_BERLIN_DATA),
                         sizeof(EUROPE_BERLIN_DATA)));

    baltzo::DefaultZoneinfoCache::setDefaultCache(&testCache);

    switch (test) { case 0:
      case 7: {
        // --------------------------------------------------------------------
        // USAGE EXAMPLE
        //   Extracted from component header file.
        //
        // Concerns:
        // 1. The usage example provided in the component header file compiles,
        //    links, and runs as shown.
        //
        // Plan:
        // 1. Incorporate usage example from header into test driver, remove
        //    leading comment characters, and replace `assert` with `ASSERT`.
        //    (C-1)
        //
        // Testing:
        //   USAGE EXAMPLE
        // --------------------------------------------------------------------

        if (verbose) cout << endl
                          << "USAGE EXAMPLE" << endl
                          << "=============" << endl;

        UsageExample1::main1();

      } break;
      case 6: {
        // --------------------------------------------------------------------
        // CALLBACK FUNCTION
        //
        // Concerns:
        // 1. The callback function loads the correct offset and returns 0 for
        //    arbitrary Zoneinfo timezones for arbitrary UTC datetimes.
        //
        // 2. For a given timezone, the callback function updates the cached
        //    local time offset information on transitions into and out of
        //    daylight saving time.
        //
        // 3. The value returned by the `updateCall` method increases by one
        //    for each transition into and out of daylight saving time, and for
        //    no other invocations of the callback.
        //
        // Plan:
        // 1. Using the array-driven approach, compare the results of calling
        //    to those obtained from an independent source.  (C-1)
        //
        // 2. Using the array-driven approach, for a fixed timezone, invoke the
        //    call back method on both sides of the boundaries of daylight
        //    saving time for a year.  Confirm that the expected values are
        //    returned throughout, and that the static members are updated when
        //    times transition into and out of daylight saving time.  Also
        //    confirm the same behavior when the series of datetimes are used
        //    in reverse order.  (C-2..3)
        //
        // Testing:
        //  void loadLocalTimeOffset(int *result, const bdlt::Datetime& utc);
        //  bsls::TimeInterval loadLocalTimeOffset(const bdlt::Datetime& utc);
        //  int updateCount();
        // --------------------------------------------------------------------

        if (verbose) cout << endl
                          << "CALLBACK FUNCTION" << endl
                          << "=================" << endl;

        if (verbose) cout << "\nCheck arbitrary timezones and UTCs" << endl;
        {
            for (int i = 0; i < DEFAULT_NUM_TZ_ARRAY; ++i) {
                const char *TIMEZONE = DEFAULT_TZ_ARRAY[i];

                if (veryVerbose) { P(TIMEZONE) }

                for (int j = 0; j < DEFAULT_NUM_DT_ARRAY; ++j) {
                    const bdlt::Datetime& UTC = DEFAULT_DT_ARRAY[j];
                    int                  status;

                    if (veryVerbose) { T_ P(UTC) }

                    baltzo::LocalTimePeriod expected;
                    status = baltzo::TimeZoneUtil::loadLocalTimePeriodForUtc(
                                                                    &expected,
                                                                    TIMEZONE,
                                                                    UTC);
                    ASSERT(0 == status);

                    status = Util::configure(TIMEZONE, UTC);
                    ASSERT(0 == status);

                    bsls::Types::Int64 reportedOffset =
                                     Util::localTimeOffset(UTC).totalSeconds();
                    ASSERT(expected.descriptor().utcOffsetInSeconds()
                        == reportedOffset);
#ifndef BDE_OMIT_INTERNAL_DEPRECATED
                    int loadOffset;
                    Util::loadLocalTimeOffset(&loadOffset, UTC);
                    ASSERT(reportedOffset == loadOffset);
#endif
                }
            }
        }

        if (verbose) cout << "\nCheck daylight saving transitions" << endl;
        {
            bdlt::Datetime newYearsDay(2013,  1,  1, 0);
            int status = Util::configure("America/New_York", newYearsDay);
            ASSERT(0 == status);

            bdlt::Datetime  startOfDst(2013,  3, 10, 7);
            bdlt::Datetime resumeOfStd(2013, 11,  3, 6);

            bdlt::Datetime startOfDstMinus(startOfDst);
                          startOfDstMinus.addMilliseconds(-1);

            bdlt::Datetime startOfDstPlus(startOfDst);
                          startOfDstPlus.addMilliseconds(1);

            bdlt::Datetime resumeOfStdMinus(resumeOfStd);
                          resumeOfStdMinus.addMilliseconds(-1);

            bdlt::Datetime resumeOfStdPlus(resumeOfStd);
                          resumeOfStdPlus.addMilliseconds(1);

            baltzo::LocalTimePeriod priorLocalTimePeriod;
            Util::loadLocalTimePeriod(&priorLocalTimePeriod);
            int                    priorUpdateCount     = Util::updateCount();
            bsl::string            priorTimezone;
            Util::loadTimezone(&priorTimezone);

            const struct {
                int           d_line;
                bdlt::Datetime d_utcDatetime;
                int           d_expectedOffset;
            } DATA[] = {

                //LINE UTC_DATETIME      EXP. OFFSET
                //---- ----------------  -----------
                { L_,  startOfDstMinus,    -5 * 3600 },
                { L_,  startOfDst,         -4 * 3600 },
                { L_,  startOfDstPlus,     -4 * 3600 },

                { L_,  resumeOfStdMinus,   -4 * 3600 },
                { L_,  resumeOfStd,        -5 * 3600 },
                { L_,  resumeOfStdPlus,    -5 * 3600 },
            };
            const int NUM_DATA = sizeof DATA / sizeof *DATA;

            for (int ti = 0; ti < NUM_DATA; ++ti) {
                const int             LINE         = DATA[ti].d_line;
                const bdlt::Datetime& UTC_DATETIME = DATA[ti].d_utcDatetime;
                const int             EXP_OFFSET   = DATA[ti].d_expectedOffset;

                if (veryVeryVerbose) { T_ P(ti) }
                if (veryVerbose) { T_ P_(LINE) P_(UTC_DATETIME) P(EXP_OFFSET) }

                bsls::Types::Int64 reportedOffset =
                            Util::localTimeOffset(UTC_DATETIME).totalSeconds();
                ASSERT(EXP_OFFSET == reportedOffset);

                {
                    bsl::string timezone; Util::loadTimezone(&timezone);
                    LOOP_ASSERT(LINE, priorTimezone == timezone); // invariant
                }
                {
                    std::string timezone; Util::loadTimezone(&timezone);
                    LOOP_ASSERT(LINE, priorTimezone == timezone); // invariant
                }
#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR_STRING
                {
                    std::pmr::string timezone; Util::loadTimezone(&timezone);
                    LOOP_ASSERT(LINE, priorTimezone == timezone); // invariant
                }
#endif

                if (ti > 0 && DATA[ti - 1].d_expectedOffset != EXP_OFFSET) {
                    baltzo::LocalTimePeriod localTimePeriod;
                    Util::loadLocalTimePeriod(&localTimePeriod);
                    LOOP_ASSERT(LINE, priorLocalTimePeriod != localTimePeriod);
                    LOOP_ASSERT(LINE, priorUpdateCount + 1 ==
                                                          Util::updateCount());

                } else {
                    baltzo::LocalTimePeriod localTimePeriod;
                    Util::loadLocalTimePeriod(&localTimePeriod);
                    LOOP_ASSERT(LINE, priorLocalTimePeriod == localTimePeriod);
                    LOOP_ASSERT(LINE, priorUpdateCount     ==
                                                          Util::updateCount());
                }

                priorUpdateCount = Util::updateCount();
                Util::loadTimezone(&priorTimezone);
                Util::loadLocalTimePeriod(&priorLocalTimePeriod);
            }

            ASSERT(0 <= NUM_DATA - 1);

            for (int ti = NUM_DATA - 1; 0 <= ti; --ti) {
                const int             LINE         = DATA[ti].d_line;
                const bdlt::Datetime& UTC_DATETIME = DATA[ti].d_utcDatetime;
                const int             EXP_OFFSET   = DATA[ti].d_expectedOffset;

                if (veryVeryVerbose) { T_ P(ti) }
                if (veryVerbose) { T_ P_(LINE) P_(UTC_DATETIME) P(EXP_OFFSET) }

                bsls::Types::Int64 reportedOffset =
                            Util::localTimeOffset(UTC_DATETIME).totalSeconds();
                ASSERT(EXP_OFFSET == reportedOffset);

                {
                    bsl::string timezone; Util::loadTimezone(&timezone);
                    LOOP_ASSERT(LINE, priorTimezone == timezone); // invariant
                }
                {
                    std::string timezone; Util::loadTimezone(&timezone);
                    LOOP_ASSERT(LINE, priorTimezone == timezone); // invariant
                }
#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR_STRING
                {
                    std::pmr::string timezone; Util::loadTimezone(&timezone);
                    LOOP_ASSERT(LINE, priorTimezone == timezone); // invariant
                }
#endif

                if (ti < NUM_DATA - 1
                 && DATA[ti + 1].d_expectedOffset != EXP_OFFSET) {
                    baltzo::LocalTimePeriod localTimePeriod;
                    Util::loadLocalTimePeriod(&localTimePeriod);
                    LOOP_ASSERT(LINE, priorLocalTimePeriod != localTimePeriod);
                    LOOP_ASSERT(LINE, priorUpdateCount + 1 ==
                                                          Util::updateCount());

                } else {
                    baltzo::LocalTimePeriod localTimePeriod;
                    Util::loadLocalTimePeriod(&localTimePeriod);
                    LOOP_ASSERT(LINE, priorLocalTimePeriod == localTimePeriod);
                    LOOP_ASSERT(LINE, priorUpdateCount     ==
                                                          Util::updateCount());
                }

                priorUpdateCount = Util::updateCount();
                Util::loadTimezone(&priorTimezone);
                Util::loadLocalTimePeriod(&priorLocalTimePeriod);
            }
        }
      } break;
      case 5: {
        // --------------------------------------------------------------------
        // STATIC INITIALIZATION
        //
        // Concerns:
        // 1. The `updateCount` method returns 0 before configuration.
        //
        // 2. The static members of `baltzo::LocalTimeOffsetUtil` that take
        //    allocators use the default global allocator.
        //
        // Plan:
        // 1. Before any other use of `baltzo::LocalTimeOffsetUtil`, check the
        //    value returned by the `updateCount` method.
        //
        // 2. Install the test allocators as the default and global allocators.
        //    Since the memory for the static members will be deleted after the
        //    return of `main`, we use a statically initialized allocator for
        //    the global allocator which will outlive the static members.
        //
        // 3. Using `baltzo::TestLoader` and several helper functions, define a
        //    time zone with a description and a timezone name sufficiently
        //    long as to require memory allocation from `bsl::string` (which
        //    has a short string optimization).  Construct a
        //    `baltzo::ZoneinfoCache` using the configured test loader and
        //    install that cache as the default timezone cache.
        //
        // 4. Configure our mechanism to use the custom-made timezone.  Check
        //    the block count of each allocator before and after configuration
        //    and compare to the expected values.
        //
        // Testing:
        //  CONCERN: This component uses the global allocator.
        // --------------------------------------------------------------------

        if (verbose) cout << endl
                          << "STATIC INITIALIZATION" << endl
                          << "=====================" << endl;

        if (verbose) cout << "\nCheck Initial Values" << endl;
        {
            ASSERT(0 == Util::updateCount());
        }

        if (verbose) cout << "\nCheck For Global Allocators" << endl;
        {
            const char LONG_DESCRIPTION[] = "Description: "
                                                      SUFFICIENTLY_LONG_STRING;
            const char LONG_TIMEZONE[]    = "Timezone: "
                                                      SUFFICIENTLY_LONG_STRING;

            const TransitionDescription TZ_DATA[] = {
              { L_, "0001-01-01T00:00:00.000",     0, "A",              false},
              { L_, "2013-01-01T12:00:00.000",  1439, LONG_DESCRIPTION, false},
              { L_, "9999-12-31T23:59:59.000",     0, "B",              false}
             };
            const int NUM_TZ_DATA = sizeof TZ_DATA / sizeof *TZ_DATA;

            baltzo::Zoneinfo testZoneInfo;
            addTransitions(&testZoneInfo, TZ_DATA, NUM_TZ_DATA);
            testZoneInfo.setIdentifier(LONG_TIMEZONE);
            ASSERT(baltzo::ZoneinfoUtil::isWellFormed(testZoneInfo));

            baltzo::TestLoader testLoader;
            testLoader.setTimeZone(testZoneInfo);

            baltzo::ZoneinfoCache testCache(&testLoader);
            baltzo::DefaultZoneinfoCache::setDefaultCache(&testCache);

            static bslma::TestAllocator staticGlobalAllocator(
                                                          "global",
                                                          veryVeryVeryVerbose);

            bslma::Default::setGlobalAllocator(&staticGlobalAllocator);

            bslma::TestAllocator         da("default", veryVeryVeryVerbose);
            bslma::DefaultAllocatorGuard dag(&da);

            ASSERT(0 == staticGlobalAllocator.numBlocksInUse());
            ASSERT(0 == da.numBlocksInUse());

            int status = Util::configure(LONG_TIMEZONE,
                                         bdlt::Datetime(2013, 1, 1, 12));
            (void)status;

            ASSERT(2 == staticGlobalAllocator.numBlocksInUse());
            ASSERT(0 == da.numBlocksInUse());
        }

      } break;
      case 4: {
        // --------------------------------------------------------------------
        // SETTING THE LOCAL TIME OFFSET CALLBACK
        //
        // Concerns:
        // 1. The `setLoadLocalTimeOffsetCallback` method sets the
        //    `localTimeOffset` method as the current local time offset
        //    callback used by `bdlt::CurrentTime`.
        //
        // 2. The `setLoadLocalTimeOffsetCallback` method returns the installed
        //    previously callback.
        //
        // Plan:
        // 1. Use the `bdlt::CurrentTime::currentLocalTimeOffsetCallback`
        //    method to check the current local time offset callback before and
        //    after calls to `setLoadLocalTimeOffsetCallback`.  (C-1)
        //
        // 2. Compare the value returned by the initial call to the
        //    `bdlt::CurrentTime::currentLocalTimeOffsetCallback` method with
        //    that returned by the `setLoadLocalTimeOffsetCallback` method.
        //    (C-2)
        //
        // Testing:
        //   bdlt::CurrentTime::LLTOC setLoadLocalTimeOffsetCallback();
        // --------------------------------------------------------------------

        if (verbose) cout << endl
                          << "SETTING THE LOCAL TIME OFFSET CALLBACK" << endl
                          << "======================================" << endl;

        const bdlt::LocalTimeOffset::LocalTimeOffsetCallback initialCallback =
                              bdlt::LocalTimeOffset::localTimeOffsetCallback();
        ASSERT(&Util::localTimeOffset != initialCallback);


        const bdlt::LocalTimeOffset::LocalTimeOffsetCallback previousCallback =
                                        Util::setLoadLocalTimeOffsetCallback();
        ASSERT(initialCallback == previousCallback);
        ASSERT(&Util::localTimeOffset
            == bdlt::LocalTimeOffset::localTimeOffsetCallback());

      } break;
      case 3: {
        // --------------------------------------------------------------------
        // OTHER MANIPULATORS
        //
        // Concerns:
        // 1. The other (non-primary) manipulators apply their expected default
        //    values.
        //
        // 2. The manipulators return a non-zero value when an invalid timezone
        //    is specified, and (QoI) there is no change in the static members.
        //
        // 3. The value returned by the `updateCall` method increases by one
        //    for each successful call of a `configure` method, and remains the
        //    same after unsuccessful calls.
        //
        // 4. The value returned by the `updateCall` method increases by one
        //    for each successful call of a `configure` method, and remains the
        //    same after unsuccessful calls.
        //
        // Plan:
        // 1. Invoke the non-primary manipulators and compare the results with
        //    obtained from the primary manipulator using the expected default
        //    values.  (C-1)
        //
        //    - One default value is the current UTC time which, of course,
        //      changes between the invocation of the two manipulators;
        //      however, this is only a problem in the unlikely event that the
        //      local time zone information changes in that short interval.
        //
        // 2. Save the values of the static members and call each `configure`
        //    method with an unknown timezone.  After each `configure` call,
        //    check the return value, and compare the current values of the
        //    static members to the saved values.  (C-2..4)
        //
        // Testing:
        //   int configure();
        //   int configure(const char *timezone);
        // --------------------------------------------------------------------

        if (verbose) cout << endl
                          << "OTHER MANIPULATORS" << endl
                          << "==================" << endl;

        int      updateCount = Util::updateCount();
        int priorUpdateCount = Util::updateCount();
        ASSERT(0 ==      updateCount);
        ASSERT(0 == priorUpdateCount);

        if (verbose) cout << "\nTesting `configure(const char *timezone)`"
                          << endl;
        {
            for (int i = 0; i < DEFAULT_NUM_TZ_ARRAY; ++i) {
                const char *TIMEZONE = DEFAULT_TZ_ARRAY[i];

                if (veryVerbose) { P(TIMEZONE) }

                int status = Util::configure(TIMEZONE);
                ASSERT(0 == status);
                bsl::string timezone; Util::loadTimezone(&timezone);
                ASSERT(0 == strcmp(TIMEZONE, timezone.c_str()));

                updateCount = Util::updateCount();
                ASSERT(priorUpdateCount + 1 == updateCount);
                priorUpdateCount = updateCount;

                // Race: utcDatetime is changing.

                baltzo::LocalTimePeriod observedLocalTimePeriod;
                Util::loadLocalTimePeriod(&observedLocalTimePeriod);

                bdlt::Datetime now = bdlt::CurrentTime::utc();
                status = Util::configure(TIMEZONE, now);
                ASSERT(0 == status);
                baltzo::LocalTimePeriod localTimePeriod;
                Util::loadLocalTimePeriod(&localTimePeriod);
                ASSERT(localTimePeriod == observedLocalTimePeriod);

                updateCount = Util::updateCount();
                ASSERT(priorUpdateCount + 1 == updateCount);
                priorUpdateCount = updateCount;
            }
        }

        if (verbose) cout << "\nTesting `configure()` for valid timezones"
                          << endl;
        {
            static char tzEquals[] = "TZ=";

            for (int i = 0; i < DEFAULT_NUM_TZ_ARRAY; ++i) {
                const char *TIMEZONE = DEFAULT_TZ_ARRAY[i];

                if (veryVerbose) { P(TIMEZONE) }

                char buffer[80];
                ASSERT(sizeof(buffer) >
                                  sizeof(tzEquals) -1 + strlen(TIMEZONE) + 1);
                snprintf(buffer, sizeof(buffer), "%s%s", tzEquals, TIMEZONE);

                if (veryVeryVerbose) { T_ P(buffer) }

                int status = putenv(buffer);
                ASSERT(0 == status);
                ASSERT(0 == strcmp(TIMEZONE, getenv("TZ")));

                status = Util::configure();

                ASSERT(0 == status);
                bsl::string timezone; Util::loadTimezone(&timezone);
                ASSERT(0 == strcmp(TIMEZONE, timezone.c_str()));

                updateCount = Util::updateCount();
                ASSERT(priorUpdateCount + 1 == updateCount);
                priorUpdateCount = updateCount;

                // Race: The UTC datetime  is changing.

                baltzo::LocalTimePeriod observedLocalTimePeriod;
                Util::loadLocalTimePeriod(&observedLocalTimePeriod);

                bdlt::Datetime now = bdlt::CurrentTime::utc();
                status = Util::configure(TIMEZONE, now);
                ASSERT(0 == status);
                baltzo::LocalTimePeriod localTimePeriod;
                Util::loadLocalTimePeriod(&localTimePeriod);
                ASSERT(localTimePeriod == observedLocalTimePeriod);

                updateCount = Util::updateCount();
                ASSERT(priorUpdateCount + 1 == updateCount);
                priorUpdateCount = updateCount;
            }
        }

        if (verbose) cout << "\nTesting Manipulators with invalid timezone"
                          << endl;
        {
            int         status;
            const char *invalidTimezone =    "FOO";
            char buffer[]               = "TZ=FOO";

            bsl::string timezone0;
            Util::loadTimezone(&timezone0);
            baltzo::LocalTimePeriod localTimePeriod0;
            Util::loadLocalTimePeriod(&localTimePeriod0);

            if (veryVeryVerbose) { T_ P(invalidTimezone) }

            {
                LogVerbosityGuard guard;
                status = Util::configure(invalidTimezone);
            }

            ASSERT(0                != status);
            bsl::string timezone; Util::loadTimezone(&timezone);
            ASSERT(timezone0        == timezone);
            baltzo::LocalTimePeriod localTimePeriod;
            Util::loadLocalTimePeriod(&localTimePeriod);
            ASSERT(localTimePeriod0 == localTimePeriod);

            updateCount = Util::updateCount();
            ASSERT(priorUpdateCount == updateCount);

            if (veryVeryVerbose) { T_ P(buffer) }

            status = putenv(buffer);
            ASSERT(0 == status);
            ASSERT(0 == strcmp(invalidTimezone, getenv("TZ")));

            {
                LogVerbosityGuard guard;
                status = Util::configure();
            }

            ASSERT(0                != status);
            Util::loadTimezone(&timezone);
            Util::loadLocalTimePeriod(&localTimePeriod);
            ASSERT(localTimePeriod0 == localTimePeriod);

            updateCount = Util::updateCount();
            ASSERT(priorUpdateCount == updateCount);
        }

      } break;
      case 2: {
        // --------------------------------------------------------------------
        // PRIMARY MANIPULATOR and BASIC ACCESSORS
        //
        // Concerns:
        // 1. The primary manipulator can set the cached local time offset
        //    information for any entry in the Zoneinfo database for arbitrary
        //    UTC datetime.
        //
        // 2. The basic accessors report the currently cached local time offset
        //    information.
        //
        // 3. The primary manipulator returns a non-zero value when an invalid
        //    timezone is specified, and (QoI) there is no change in the static
        //    members.
        //
        // 4. QoI: Asserted precondition violations are detected when enabled.
        //
        // Plan:
        // 1. Using the array-driven approach, generate test cases for several
        //    entries representing several categories of Zoneinfo entries
        //    (i.e., timezone before and after "Etc/GMT" and "Etc/GMT" itself)
        //    and for several categories of UTC datetimes (i.e., before,
        //    during, and after daylight saving time, if defined in a
        //    timezone).  For each entry confirm that `configure` returns
        //    successfully, and use the accessors to confirm that the cached
        //    information matches the expected results.  The expected results
        //    for the local time period is obtained using the
        //    `baltzo::TimeZoneUtil::loadLocalTimePeriodForUtc` method.
        //    (C-1..2)
        //
        // 2. Save the values of the static members, call `configure` with an
        //    unknown timezone, check the return value, and compare the current
        //    values of the static members to the saved values.
        //
        // 3. Verify that, in appropriate build modes, defensive checks are
        //    triggered for invalid attribute values, but not triggered for
        //    adjacent valid ones (using the `BSLS_ASSERTTEST_*` macros).
        //    (C-4)
        //
        // Testing:
        //   int configure(const char *timezone, const bdlt::Datetime& utc);
        //   void loadLocalTimePeriod(LocalTimePeriod *localTimePeriod);
        //   bsl::string loadTimezone(bsl::string      *timezone);
        //   bsl::string loadTimezone(std::string      *timezone);
        //   bsl::string loadTimezone(std::pmr::string *timezone);
        // --------------------------------------------------------------------

        if (verbose) cout << endl
                          << "PRIMARY MANIPULATOR and BASIC ACCESSORS" << endl
                          << "=======================================" << endl;

        int      updateCount = Util::updateCount();
        int priorUpdateCount = Util::updateCount();
        ASSERT(0 ==      updateCount);
        ASSERT(0 == priorUpdateCount);

        if (verbose) cout << "\nCheck valid timezones" << endl;
        {
            for (int i = 0; i < DEFAULT_NUM_TZ_ARRAY; ++i) {
                const char *TIMEZONE = DEFAULT_TZ_ARRAY[i];

                if (veryVerbose) { P(TIMEZONE) }

                for (int j = 0; j < DEFAULT_NUM_DT_ARRAY; ++j) {
                    const bdlt::Datetime& UTC = DEFAULT_DT_ARRAY[j];

                    if (veryVerbose) { T_ P(UTC) }

                    int status = Util::configure(TIMEZONE, UTC);
                    ASSERT(0 == status);

                    {
                        bsl::string timezone;
                        Util::loadTimezone(&timezone);
                        ASSERT(0 == strcmp(TIMEZONE, timezone.c_str()));
                    }
                    {
                        std::string timezone;
                        Util::loadTimezone(&timezone);
                        ASSERT(0 == strcmp(TIMEZONE, timezone.c_str()));
                    }
#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR_STRING
                    {
                        std::pmr::string timezone;
                        Util::loadTimezone(&timezone);
                        ASSERT(0 == strcmp(TIMEZONE, timezone.c_str()));
                    }
#endif

                    updateCount = Util::updateCount();
                    ASSERT(priorUpdateCount + 1 == updateCount);
                    priorUpdateCount = updateCount;

                    baltzo::LocalTimePeriod expectedLocalTimePeriod;

                    status = baltzo::TimeZoneUtil::loadLocalTimePeriodForUtc(
                                                      &expectedLocalTimePeriod,
                                                      TIMEZONE,
                                                      UTC);
                    ASSERT(0 == status);

                    baltzo::LocalTimePeriod localTimePeriod;
                    Util::loadLocalTimePeriod(&localTimePeriod);

                    ASSERT(expectedLocalTimePeriod == localTimePeriod);
                }
            }
        }

        if (verbose) cout << "\nCheck invalid timezone" << endl;
        {
            bsl::string timezone0; Util::loadTimezone(&timezone0);
            baltzo::LocalTimePeriod localTimePeriod0;
            Util::loadLocalTimePeriod(&localTimePeriod0);

            int status;

            {
                LogVerbosityGuard guard;
                status = Util::configure("hello, world", bdlt::Datetime(2013,
                                                                          2,
                                                                         28));
            }
            bsl::string timezone; Util::loadTimezone(&timezone);
            ASSERT(0                != status);
            ASSERT(timezone0        == timezone);
            baltzo::LocalTimePeriod localTimePeriod;
            Util::loadLocalTimePeriod(&localTimePeriod);
            ASSERT(localTimePeriod0 == localTimePeriod);

            updateCount = Util::updateCount();
            ASSERT(priorUpdateCount == updateCount);
        }

        if (verbose) cout << "\nNegative Testing." << endl;
        {
            bsls::AssertTestHandlerGuard hG;

            if (veryVerbose) cout << "\t'loadLocalTimePeriod'" << endl;
            {
                baltzo::LocalTimePeriod ltp;
                ASSERT_PASS(Util::loadLocalTimePeriod(&ltp));
                ASSERT_FAIL(Util::loadLocalTimePeriod(0));
            }

            if (veryVerbose) cout << "\t'loadTimezone'" << endl;
            {
                bsl::string s, *pz = 0;
                ASSERT_PASS(Util::loadTimezone(&s));
                ASSERT_FAIL(Util::loadTimezone(pz));
            }
            {
                std::string s, *pz = 0;
                ASSERT_PASS(Util::loadTimezone(&s));
                ASSERT_FAIL(Util::loadTimezone(pz));
            }
#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR_STRING
            {
                std::pmr::string s, *pz = 0;
                ASSERT_PASS(Util::loadTimezone(&s));
                ASSERT_FAIL(Util::loadTimezone(pz));
            }
#endif
        }
      } break;
      case 1: {
        // --------------------------------------------------------------------
        // BREATHING TEST
        //   This case exercises (but does not fully test) basic functionality.
        //
        // Concerns:
        // 1. The class is sufficiently functional to enable comprehensive
        //    testing in subsequent test cases.
        //
        // Plan:
        // 1. Set the time zone to "America/New_York" for several dates in
        //    succession, and examine the local time period information at each
        //    stage.
        //
        // Testing:
        //   BREATHING TEST
        // --------------------------------------------------------------------

        if (verbose) cout << endl
                          << "BREATHING TEST" << endl
                          << "==============" << endl;

        baltzo::LocalTimePeriod localTimePeriod;

        int status1 = Util::configure(NY);
        ASSERT(0 == status1);

        if (verbose) {
            Util::loadLocalTimePeriod(&localTimePeriod);
            cout << localTimePeriod << endl;
        }

        bdlt::Datetime startOfDst(2013, 3, 10, 7);
        int status2 = Util::configure(NY, startOfDst);
        ASSERT(0 == status2);

        if (verbose) {
            Util::loadLocalTimePeriod(&localTimePeriod);
            cout << localTimePeriod << endl;
        }

        bdlt::Datetime resumeOfStd(2013, 11, 3, 6);
        int status3 = Util::configure(NY, resumeOfStd);
        ASSERT(0 == status3);

        if (verbose) {
            Util::loadLocalTimePeriod(&localTimePeriod);
            cout << localTimePeriod << endl;
        }

      } break;
      case -1: {
        // --------------------------------------------------------------------
        // THREAD SAFETY
        //   The primary concern is the thread-safety of the
        //   `localTimeOffset` method.  The other public methods will
        //   typically be called once near the start of a process, and before
        //   multiple threads are launched.  Since the limit on thread creation
        //   vary significantly with platform, this test is designed to be run
        //   interactively (i.e., the test has a negative test number).
        //
        // Concerns:
        // 1. Concurrent threads calling the `localTimeOffset` method each
        //    receive the correct result and return value indicating success.
        //
        // 2. When needed, the cached local time zone information is updated
        //    exactly once.
        //
        // Plan:
        // 1. Set the timezone and UTC time to some day in 2013 before the
        //    start of daylight saving time in New York).
        //
        // 2. Launch multiple threads (where the number is determined by a
        //    command-line argument) that each wait at a common barrier until
        //    all the threads have been created, and then invoke the
        //    `localTimeOffset` method requesting the offset for the start
        //    of daylight saving time.
        //
        // 3. Compare the values obtained by each thread with the expected
        //    offset for the start of daylight saving time.
        //
        // 4. Confirm that the value returned by `updateCount` increased by
        //    exactly one.
        //
        // 5. Repeat the test a number of times specified by a command-line
        //    argument.
        //
        // Testing:
        //   CONCERN: The public methods of this component are *thread-safe*.
        // --------------------------------------------------------------------

        if (verbose) cout << endl
                          << "THREAD SAFETY" << endl
                          << "=============" << endl;

        const int numThreads    = argc > 2 ? atoi(argv[2]) : 1;
        const int numIterations = argc > 3 ? atoi(argv[3]) : 1;

        P(numThreads)
        P(numIterations)

        bslmt::Configuration::setDefaultThreadStackSize(
                    bslmt::Configuration::recommendedDefaultThreadStackSize());

        const bdlt::Datetime newYearsDay(2013, 1,  1);
        const bdlt::Datetime  startOfDst(2013, 3, 10, 7);
        const char          *timezone             = "America/New_York";
        int                  previousUpdateCount = Util::updateCount();

        ASSERT(0 == previousUpdateCount);

        bsls::Stopwatch stopwatch;
        stopwatch.start(true);

        for (int i = 0;  i < numIterations; ++i) {

            int status = Util::configure(timezone, newYearsDay);
            ASSERT(0 == status);

            int updateCount = Util::updateCount();
            ASSERT(previousUpdateCount + 1 == updateCount);
            previousUpdateCount = updateCount;

            Handles       handles(numThreads);
            ThreadArgs threadArgs(numThreads);

            bslmt::Barrier   barrier(numThreads);

            // Setup and launch threads.

            for (int j = 0; j < numThreads; ++j) {
                threadArgs[j].d_offset      = 0x0BADCAFE;
                threadArgs[j].d_utcDatetime = startOfDst;
                threadArgs[j].d_barrier_p   = &barrier;

                int status = bslmt::ThreadUtil::create(&handles[j],
                                                      workerThread,
                                                      &threadArgs[j]);
                ASSERT(0 == status);
            }

            // Wait for all threads to complete.


            for (Handles::iterator itr  = handles.begin(),
                                   end  = handles.end();
                                   end != itr; ++itr) {
                bslmt::ThreadUtil::join(*itr);
            }


            // Examine results.

            updateCount = Util::updateCount();
            ASSERT(previousUpdateCount + 1 == updateCount);
            previousUpdateCount = updateCount;

            for (ThreadArgs::iterator itr  = threadArgs.begin(),
                                      end  = threadArgs.end();
                                      end != itr; ++itr) {
                ASSERT(-4 * 3600 == itr->d_offset);
            }

        }

        stopwatch.stop();

        double systemTime;
        double   userTime;
        double   wallTime;

        stopwatch.accumulatedTimes(&systemTime, &userTime, &wallTime);
        P_(systemTime) P_(userTime) P(wallTime)

      } break;
      case -2: {
        // --------------------------------------------------------------------
        // PERFORMANCE: CACHE-HITS
        //
        // Concerns:
        // 1. The time needed to deliver an offset value from the cached
        //    information should be known.
        //
        // Plan:
        // 1. Set the timezone and UTC time to some day in 2013 before the
        //    start of daylight saving time in New York).
        //
        // 2. Use a stopwatch mechanism to measure the time needed to
        //    iteratively request the local time offset at the UTC datetime set
        //    in P-1.  The number of iterations is determined by a command-line
        //    parameter.  (C-1)
        //
        // Testing:
        //   CONCERN: Performance on cache hits.
        // --------------------------------------------------------------------

        if (verbose) cout << endl
                          << "PERFORMANCE: CACHE-HITS" << endl
                          << "=======================" << endl;

        const int numIterations = argc > 2 ? atoi(argv[2]) : 0;

        P(numIterations);

        const bdlt::Datetime newYearsDay(2013, 1,  1);
        const char          *timezone             = "America/New_York";

        int status = Util::configure(timezone, newYearsDay);
        ASSERT(0 == status);

        // Confirm that the callback is working

        bsls::Types::Int64 offset =
                             Util::localTimeOffset(newYearsDay).totalSeconds();
        (void)offset;

        bsls::Stopwatch stopwatch;
        stopwatch.start(true);

        for (int i = 0;  i < numIterations; ++i) {
            offset = Util::localTimeOffset(newYearsDay).totalSeconds();
        }

        double systemTime;
        double   userTime;
        double   wallTime;
        stopwatch.accumulatedTimes(&systemTime, &userTime, &wallTime);

        P_(systemTime) P_(userTime) P(wallTime);

      } break;
      case -3: {
        // --------------------------------------------------------------------
        // PERFORMANCE: CACHE MISSES
        //
        // Concerns:
        // 1. The time needed to deliver an offset value when the information
        //    is not in the cache information should be known.
        //
        // Plan:
        // 1. Set the timezone and UTC time to some day in 2013 before the
        //    start of daylight saving time in New York).
        //
        // 2. Use a stopwatch mechanism to measure the time needed to
        //    iteratively request the local time offset at the UTC datetime
        //    corresponding to the start of daylight saving time in New York,
        //    a cache-miss, which resets the cache.  Then, request the result
        //    for the UTC time set in P-1, another cache-miss.  The number of
        // requests is determined by a command-line parameter.
        //    parameter.  (C-1)
        //
        // Testing:
        //   CONCERN: Performance on cache misses.
        // --------------------------------------------------------------------

        if (verbose) cout << endl
                          << "PERFORMANCE: CACHE-MISSES" << endl
                          << "=========================" << endl;

        const int numIterations = argc > 2 ? atoi(argv[2]) : 0;

        P(numIterations);

        const bdlt::Datetime  newYearsDay(2013,  1,  1);
        const bdlt::Datetime   startOfDst(2013,  3, 10, 7);
        const char          *timezone = "America/New_York";

        int status = Util::configure(timezone, newYearsDay);
        ASSERT(0 == status);

        // Confirm that the callback is working

        bsls::Types::Int64 offset =
                             Util::localTimeOffset(newYearsDay).totalSeconds();
        (void)offset;

        const int numIterations2 = numIterations/2;

        bsls::Stopwatch stopwatch;
        stopwatch.start(true);

        for (int i = 0;  i < numIterations2; ++i) {
            offset = Util::localTimeOffset(startOfDst).totalSeconds();
            offset = Util::localTimeOffset(newYearsDay).totalSeconds();
        }

        stopwatch.stop();

        double systemTime;
        double   userTime;
        double   wallTime;
        stopwatch.accumulatedTimes(&systemTime, &userTime, &wallTime);

        P_(systemTime) P_(userTime) P(wallTime);

      } break;
      default: {
        cerr << "WARNING: CASE `" << test << "' NOT FOUND." << endl;
        testStatus = -1;
      }
    }

    if (testStatus > 0) {
        cerr << "Error, non-zero test status = " << testStatus << "." << endl;
    }
    return testStatus;
}

// ----------------------------------------------------------------------------
// Copyright 2015 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ----------------------------- END-OF-FILE ----------------------------------
